Sunday, November 4, 2012

Android based Remote Control for Mac

Here is an Android based application which enables you to control media (mp3) on the MacOS

Code is available on GitHub http:/github.com/giridharmb . It is certainly Not of production quality - this is meant for demo purposes only:-)

There are 2 parts to this project

1. Client (Android application)

2. Server (Java application which plays media and receives requests from Android device)


Client Code (Android)

File: PlayActivity.java

package com.giri.macplayercontrol;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.KeyEvent;
import android.view.Menu;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import com.giri.player.NewClient;

import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

public class PlayActivity extends Activity {

 private List mylist = new ArrayList();
 private ListView list;
 private int selectedItem = 0;
 private NewClient newClient = null;

 private void show(int value) {
  Toast.makeText(PlayActivity.this, String.valueOf(value), Toast.LENGTH_SHORT).show();
 }


 private String fetchIPAddrFromTextBox() {
  String myStr = null;
  EditText editText = (EditText) findViewById(R.id.editText1);
  myStr = editText.getText().toString();
  return myStr;
 }

 private void createListView() {
  newClient = new NewClient();

  // setupButtonHandler();

  final EditText myEditText = (EditText) findViewById(R.id.editText1);
  Button btn = (Button) findViewById(R.id.button1);
  btn.setOnClickListener(new View.OnClickListener() {

   public void onClick(View v) {
    InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    mgr.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
    
    String ip = fetchIPAddrFromTextBox();

    if (ip == null)
     return;

    newClient.setSERVER_IP(ip);
    
    LinkedList ll = new LinkedList();
    ll = newClient.fetchPlayListLinkedList();
    
    mylist = new ArrayList();
      
    list = (ListView) findViewById(R.id.listView1);
      
    for (int i = 0; i < ll.size(); i++) {
     mylist.add(ll.get(i));
    }
    
    list.setAdapter(new ArrayAdapter(PlayActivity.this,android.R.layout.simple_list_item_1, mylist));
   }
  });
 
  list.setOnItemClickListener(new OnItemClickListener() {
   @Override
   public void onItemClick(AdapterView arg0, View arg1, int arg2,long arg3) {
    show(arg2);
    newClient.playIndex(arg2);
   }
  });
 }

 @Override
 public void onBackPressed() {
     moveTaskToBack(true);
 }
 
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_play);
  
  list = (ListView) findViewById(R.id.listView1);

  createListView();

 }

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_play, menu);
  return true;
 }
}

Client Code (Android)

File: AllSongsObjects.java

package com.giri.player;

import java.io.Serializable;
import java.util.LinkedList;

public class AllSongsObject implements Serializable {
 
 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private LinkedList _ll = new LinkedList();
 
 public AllSongsObject(LinkedList lls) {
  _ll = lls;
 }

 public LinkedList get_ll() {
  return _ll;
 }

 public void set_ll(LinkedList _ll) {
  this._ll = _ll;
 }
 
}

Client Code (Android)

File: Constants.java

package com.giri.player;

public class Constants {
 public static String PLAY = "COMMAND_PLAY";
 public static String STOP = "COMMAND_STOP";
 public static String PLAYRANDOM = "COMMAND_PRANDOM";
 public static String VOLUMEUP = "COMMAND_VOLUMEUP";
 public static String VOLUMEDOWN = "COMMAND_VOLUMEDOWN";
 public static String VOLUMESET = "COMMAND_VOLUMESET@";
 public static String GETPLAYLIST = "COMMAND_GETPLAYLIST";
 public static String PLAYINDEX = "COMMAND_PLAYINDEX@";
 public static String LOOP = "COMMAND_LOOP";
 public static String DONTLOOP = "COMMAND_DONTLOOP";
}

Client Code (Android)

File: Message.java

package com.giri.player;


import java.io.Serializable;

public class Message implements Serializable{

    /**
  * 
  */
 private static final long serialVersionUID = 1L;
 
 private String message;

    public Message(String message) {
        this.message = message;
    }

    public String getMessage(){
        return message;
    }
}

Client Code (Android)

File: NewClient.java

package com.giri.player;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.LinkedList;

import com.giri.player.AllSongsObject;
import com.giri.player.Constants;
import com.giri.player.Message;

public class NewClient {

    private  String SERVER_IP = "192.168.0.89";
    private  int SERVER_PORT = 8081;
    private  String message = null;
    private static Socket socket = null;

    private LinkedList<String> playList = new LinkedList<String>();
 
    public NewClient() {
     
    }
    
   public NewClient(String msg) {
     message = msg;
    }

    public String getSERVER_IP() {
  return SERVER_IP;
 }
 public void setSERVER_IP(String sERVER_IP) {
  SERVER_IP = sERVER_IP;
 }
 public int getSERVER_PORT() {
  return SERVER_PORT;
 }
 public void setSERVER_PORT(int sERVER_PORT) {
  SERVER_PORT = sERVER_PORT;
 }
 public LinkedList<String> getPlayList() {
  return playList;
 }
 public void setPlayList(LinkedList<String> playList) {
  this.playList = playList;
 }
   
    public String getMessage() {
  return message;
 }
 public void setMessage(String message) {
  this.message = message;
 }
 
 public void playIndex(int value) {
  
  Object obj = null;
        
        try
        {
         //if(socket!=null) {
         // if(!socket.isClosed()) {
         //  socket.close();
         // }
         //}
            socket = new Socket(SERVER_IP, SERVER_PORT);
            socket.setReuseAddress(true);
            System.out.println("# Client # : Connected to server!");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
         System.out.println("# Client # : Error connecting to server: " + ex.getMessage());
        }

        ObjectInputStream in = null;
        ObjectOutputStream out = null;

 
        try
        {
    
            out = new ObjectOutputStream(socket.getOutputStream());

            //read a string
            
            System.out.println("# Client # : Message entered is: " + Constants.PLAYINDEX+Integer.toString(value));

            //send it to server
            out.writeObject(new Message(Constants.PLAYINDEX+Integer.toString(value)));
            out.flush();
            
            System.out.println("# Client # : Reading from input stream...");
      
            in = new ObjectInputStream(socket.getInputStream());
            
            obj = (Object) in.readObject();
      
        }
        catch (Exception ex)
        {
         ex.printStackTrace();
            System.out.println("# Client # : Error: " + ex);
        }
        finally
        {
         try 
         {
             out.close();
             //socket.close();
         } catch(Exception e)
         {
          e.printStackTrace();
         }
        }
 }
 
 public LinkedList<String> fetchPlayListLinkedList() {
  
  LinkedList<String> ll = new LinkedList<String>();

        AllSongsObject aso = null;
        
        try
        {
         //if(socket != null) {
      // if(!socket.isClosed()) {
      //  socket.close();
      // }
         //}
            socket = new Socket(SERVER_IP, SERVER_PORT);
            System.out.println("# Client # : Connected to server!");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
         System.out.println("# Client # : Error connecting to server: " + ex.getMessage());
        }

        ObjectInputStream in = null;
        ObjectOutputStream out = null;

 
        try
        {
    
            out = new ObjectOutputStream(socket.getOutputStream());

            //read a string
            
            System.out.println("# Client # : Message entered is: " + Constants.GETPLAYLIST);

            //send it to server
            out.writeObject(new Message(Constants.GETPLAYLIST));
            out.flush();
            
            System.out.println("# Client # : Reading from input stream...");
      
            in = new ObjectInputStream(socket.getInputStream());
            
            aso = (AllSongsObject) in.readObject();
            
            System.out.println("# Client # : Server returned object of size: " + aso.get_ll().size());
            
            System.out.println("# Client # : Contents of the list: ");
            
            for(int i=0; i<aso.get_ll().size(); i++) {
             System.out.println(aso.get_ll().get(i));
            }
            
            ll = aso.get_ll();

        }
        catch (Exception ex)
        {
         ex.printStackTrace();
            System.out.println("# Client # : Error: " + ex);
        }
        finally
        {
         try 
         {
             out.close();
             //socket.close();
         } catch(Exception e)
         {
          e.printStackTrace();
         }
        }
        return ll;
 }
 
 public void MainMethod()
    {
        AllSongsObject aso = null;
        
        try
        {
         //if(socket != null) {
         // if(!socket.isClosed()) {
         //  socket.close();
         // }
         //}
            socket = new Socket(SERVER_IP, SERVER_PORT);
            System.out.println("# Client # : Connected to server!");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
         System.out.println("# Client # : Error connecting to server: " + ex.getMessage());
        }

        ObjectInputStream in = null;
        ObjectOutputStream out = null;

 
        try
        {
    
            out = new ObjectOutputStream(socket.getOutputStream());

            //read a string
            
            System.out.println("# Client # : Message entered is: " + message);

            //send it to server
            out.writeObject(new Message(message));
            out.flush();
            
            System.out.println("# Client # : Reading from input stream...");
      
            in = new ObjectInputStream(socket.getInputStream());
            
            aso = (AllSongsObject) in.readObject();
            
            System.out.println("# Client # : Server returned object of size: " + aso.get_ll().size());
            
            System.out.println("# Client # : Contents of the list: ");
            
            for(int i=0; i<aso.get_ll().size(); i++) {
             System.out.println(aso.get_ll().get(i));
            }

        }
        catch (Exception ex)
        {
         ex.printStackTrace();
            System.out.println("# Client # : Error: " + ex);
        }
        finally
        {
         try 
         {
             out.close();
             //socket.close();
         } catch(Exception e)
         {
          e.printStackTrace();
         }
        }
    }
    
    public void execute() {
     new NewClient().MainMethod();
    }
    
}

Server Code (Java application running on Mac OS X)

1 >> File: AllSongsObject.java

package com.giri.player;

import java.io.Serializable;
import java.util.LinkedList;

public class AllSongsObject implements Serializable {
 
 /**
  * 
  */
 private static final long serialVersionUID = 1L;

 private LinkedList _ll = new LinkedList();
 
 public AllSongsObject(LinkedList lls) {
  _ll = lls;
 }

 public LinkedList get_ll() {
  return _ll;
 }

 public void set_ll(LinkedList _ll) {
  this._ll = _ll;
 }
 
}

Server Code (Java application running on Mac OS X)

2 >> File: AllSongsObjectRequest.java

package com.giri.player;

public class AllSongsObjectRequest extends Request {

 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 
 private static int _index = 0;
 
 public AllSongsObjectRequest(int n) {
  _index = n;
 }
 
 public Object execute() {
  return _index;
 }

}

Server Code (Java application running on Mac OS X)

3 >> File: CommandRunnerTest.java

package com.giri.player;
import java.awt.List;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.concurrent.ExecutionException;
import org.apache.commons.io.*;
import javax.swing.SwingWorker;

public class CommandRunnerTest implements Runnable {
  
 private String[] cmdToRun = null;
 public static int retCode = -1;

 public int getRetCode() {
  return retCode;
 }

 public void setRetCode(int retCode) {
  this.retCode = retCode;
 }
 
 public String[] getCmdToRun() {
  return cmdToRun;
 }

 public void setCmdToRun(String[] cmdToRun) {
  this.cmdToRun = cmdToRun;
 }

 public CommandRunnerTest(String[] cmd) {
  cmdToRun = cmd;
 }

 @Override
 public void run() {
  // TODO Auto-generated method stub
  try {

   String[] killCmd = {"killall" ,"-9", "PlayFile"};
   Process pKill = Runtime.getRuntime().exec(killCmd);
   pKill.waitFor();
   
   MainProcess.p = Runtime.getRuntime().exec(cmdToRun);
   
   retCode = MainProcess.p.waitFor();
   System.out.println("** Exit Code: " + retCode);
   
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
}

Server Code (Java application running on Mac OS X)

4 >> File: Constants.java

package com.giri.player;

public class Constants {
 public static String PLAY = "COMMAND_PLAY";
 public static String STOP = "COMMAND_STOP";
 public static String PLAYRANDOM = "COMMAND_PRANDOM";
 public static String VOLUMEUP = "COMMAND_VOLUMEUP";
 public static String VOLUMEDOWN = "COMMAND_VOLUMEDOWN";
 public static String VOLUMESET = "COMMAND_VOLUMESET@";
 public static String GETPLAYLIST = "COMMAND_GETPLAYLIST";
 public static String PLAYINDEX = "COMMAND_PLAYINDEX@";
 public static String LOOP = "COMMAND_LOOP";
 public static String DONTLOOP = "COMMAND_DONTLOOP";
 public static String GETVOLUME = "COMMAND_GETVOLUME";
 public static String SETVOLUME = "COMMAND_SETVOLUME@";
 
}

Server Code (Java application running on Mac OS X)

5 >> File: MainPlayer.java


package com.giri.player;

public interface MainPlayer {
 public void _play();
 public void _stop();
 public void _exit();
 public void _playrandom();
 public void _setvolume(int volume);
}

Server Code (Java application running on Mac OS X)

6 >> File: MainProcess.java

package com.giri.player;

public class MainProcess {
 public static Process p = null;
}

Server Code (Java application running on Mac OS X)

7 >> File: MainWindow.java

package com.giri.player;


import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.JButton;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLDecoder;
import java.util.LinkedList;
import java.util.Random;

import java.lang.*;
import java.io.*;
import java.net.*;


import javax.swing.JLabel;
import javax.swing.SwingConstants;
import java.awt.List;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import org.apache.commons.io.*;
import org.apache.commons.io.filefilter.WildcardFileFilter;
import javax.swing.JScrollBar;
import javax.swing.JTextField;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.beans.VetoableChangeListener;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JCheckBox;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;


public class MainWindow extends JFrame implements MainPlayer {

 /**
  * 
  */
 private static final long serialVersionUID = 1L;
 private JPanel contentPane;
 private Process p_volume = null;
 private JFileChooser fc = null;
 public static LinkedList allSongsLinkedList = new LinkedList();
 public static LinkedList allSongsFileNamesOnly = new LinkedList();
 private List list = null;
   
 //public static CommandRunnerTest CR = new CommandRunnerTest();
 
 private static NewServer server_thread = null;
 private static ProcessMonitor processMonitor = null;
 public static Thread thread_ProcessMonitor = new Thread("ProcessMonitor");
 
 public static boolean REPLAY_NOW = false;
 
 public static PlayerState CurrentPlayerState;
 private JTextField textField;
 private JScrollBar scrollBar = null;
 
 public static boolean keepPlaying =false;
 
 public static JCheckBox chckbxNewCheckBox = null;
  
 
 // System.getProperty("user.home")
    
 
 public static void PLAY(int index) {
  playIndex(index);
 }
 
 private void populateList() {
  allSongsLinkedList = getAllFiles(System.getProperty("user.home")+"/__media__","mp3");
 }
 
 // fileDir = /Users/giridhar/songs/english , extension = mp3
 private LinkedList getAllFiles(String fileDir, String extension) {
  System.out.println("getAllFiles(), Input fileDir="+fileDir+", extension="+extension);
  LinkedList myLinkedList = new LinkedList();
  File dir = new File(fileDir);
  FileFilter fileFilter = new WildcardFileFilter("*." + extension);
  File[] files = dir.listFiles(fileFilter);
   
  for(File f : files) {
   String absPathOfFile = f.getAbsolutePath();
   myLinkedList.add(absPathOfFile);
   list.add(f.getName());
   allSongsFileNamesOnly.add(f.getName());
  }
  System.out.println("Size of myLinkedList returned: "+myLinkedList.size());
  return myLinkedList;
 }
 
 private void setVolumeTextAndVolume(int level) {
  _setvolume(level);
 }
 
 public synchronized static void setVolume(int level) {
  if(level>=0 && level<=100) {
   String volume = Integer.toString(level);
   String cmd[] = { "osascript", "/bin/getsetvolume.scpt" ,"SET", volume };
   try {
    Process volProc = Runtime.getRuntime().exec(cmd);
    volProc.waitFor();
   } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }

 private synchronized void playFile(File f) {
  
  String pathToFile = f.getAbsolutePath();
  String playCommand = "PlayFile " + pathToFile;
  String[] playCmd = { "PlayFile" , pathToFile };
  new Thread(new CommandRunnerTest(playCmd),"Command Runner").start();
  //CR.setCmdToRun(playCmd);
  //CR.EXECUTE();
  
 }
 
 public static String getVolume()  {
  String ret = null;
  String line = null;
  String cmd[] = { "osascript", "/bin/getsetvolume.scpt" ,"GET" };
  try {
   Process volProc = Runtime.getRuntime().exec(cmd);
   volProc.waitFor();
   BufferedReader in = new BufferedReader(new InputStreamReader(volProc.getInputStream()) );
      while ((line = in.readLine()) != null)
      {
       System.out.println(line);
       ret = line.toString();
       break;
      }
      
      in.close();
  } catch (Exception e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  return ret; 
 }
 
 /**
  * Launch the application.
  */
 public static void main(String[] args) {
  
        System.setProperty("Quaqua.tabLayoutPolicy","wrap");
        
        try { 
             UIManager.setLookAndFeel(ch.randelshofer.quaqua.QuaquaManager.getLookAndFeel());
        } catch (Exception e) {
        
            e.printStackTrace();
        }
        
        processMonitor = new ProcessMonitor();
        thread_ProcessMonitor = new Thread(processMonitor);
  thread_ProcessMonitor.start();
  
  EventQueue.invokeLater(new Runnable() {
   public void run() {
    try {
     MainWindow frame = new MainWindow();
     frame.setVisible(true);
     System.out.println("# Starting server thread...");
     //Thread server_thread = new ServerThread();
     server_thread = new NewServer("testServer");
     server_thread.start();
     System.out.println("# Server thread started ...");
               
    } catch (Exception e) {
     e.printStackTrace();
    }
   }
  });
 
 }
 
 
 private void playRandomSong() {
  _playrandom();
 }
 
 private synchronized static void playIndex(int value) {
  
  System.out.println("@ Play message received. Requested index: " + value);
  
  if(value >= 0 && value < allSongsLinkedList.size() )
  {
   String fileToPlay = allSongsLinkedList.get(value);
   String playCommand = "PlayFile " + fileToPlay;
   String cmd[] = {"PlayFile", fileToPlay};
     
   System.out.println("fileToPlay: " + fileToPlay);
   System.out.println("Play Command: " + playCommand);
   
   //CR.setCmdToRun(cmd);
   //CR.EXECUTE();
   new Thread(new CommandRunnerTest(cmd),"Command Runner").start();
   
   /*
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   */
   
  }
 
 }
 
 /**
  * Create the frame.
  */
 public MainWindow() {
  
  //replayManager = new ReplayManager();
  //replayManager.start();
  
    
  setResizable(false);
  
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  setBounds(100, 100, 767, 572);
  contentPane = new JPanel();
  contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
  setContentPane(contentPane);
  contentPane.setLayout(null);
  
  CurrentPlayerState = PlayerState.STOPPED;
  
  list = new List();
  
  populateList();
  
  JButton btnPlay = new JButton("Play");
  btnPlay.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    _play();
   }
  });
  
  btnPlay.addMouseListener(new MouseAdapter() {
   @Override
   public void mouseClicked(MouseEvent arg0) {
    
   }
  });
  btnPlay.setBounds(31, 421, 117, 29);
  contentPane.add(btnPlay);
  
  JButton btnStop = new JButton("Stop");
  btnStop.addActionListener(new ActionListener() {
   
   public void actionPerformed(ActionEvent e) {
    _stop();
   }
  });
  btnStop.addMouseListener(new MouseAdapter() {
   
   @Override
   public void mouseClicked(MouseEvent e) {
   
   }
  });
  btnStop.setBounds(289, 421, 117, 29);
  contentPane.add(btnStop);
  
  JLabel lblNewLabel = new JLabel("Browse Folder");
  lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
  lblNewLabel.setBounds(6, 6, 253, 16);
  contentPane.add(lblNewLabel);
  
  JButton btnBrowse = new JButton("Browse");
  btnBrowse.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    fc = new JFileChooser();
    fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    int returnVal = fc.showOpenDialog(MainWindow.this);
    
          if (returnVal == JFileChooser.APPROVE_OPTION) {
              File file = fc.getSelectedFile();
              //This is where a real application would open the file.
              System.out.println("Selected folder: " + file.getAbsolutePath());
              allSongsLinkedList = getAllFiles(file.getAbsolutePath(),"mp3");
                            
          } else {
              System.out.println("Operation cancelled by user ...!");
          }
   }
  });
  btnBrowse.setBounds(31, 34, 707, 29);
  contentPane.add(btnBrowse);
  
  
  list.setBounds(31, 69, 709, 334);
  contentPane.add(list);
  
  JButton btnExit = new JButton("Exit");
  btnExit.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    _exit();
   }
  });
  btnExit.setBounds(418, 421, 117, 29);
  contentPane.add(btnExit);
  
  JLabel lblGiridharsMpPlayer = new JLabel("Giridhar's MP3 Player for Mac OSX (giridharmb@gmail.com)");
  lblGiridharsMpPlayer.setHorizontalAlignment(SwingConstants.CENTER);
  lblGiridharsMpPlayer.setBounds(346, 6, 415, 16);
  contentPane.add(lblGiridharsMpPlayer);
  
  JButton btnPlayRandom = new JButton("Play Random");
  btnPlayRandom.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    playRandomSong();
   }
  });
  btnPlayRandom.setBounds(160, 421, 117, 29);
  contentPane.add(btnPlayRandom);
  
  JLabel lblVolume = new JLabel("Volume");
  lblVolume.setHorizontalAlignment(SwingConstants.CENTER);
  lblVolume.setBounds(31, 479, 61, 16);
  contentPane.add(lblVolume);
  
  scrollBar = new JScrollBar();
  scrollBar.addMouseListener(new MouseAdapter() {
   @Override
   public void mouseReleased(MouseEvent arg0) {
    
   }
   @Override
   public void mouseClicked(MouseEvent e) {
    setVolumeTextAndVolume(scrollBar.getValue());
   }
  });
  scrollBar.setOrientation(JScrollBar.HORIZONTAL);
  scrollBar.addMouseMotionListener(new MouseMotionAdapter() {
   @Override
   public void mouseDragged(MouseEvent arg0) {
    setVolumeTextAndVolume(scrollBar.getValue());
   }
  });
  scrollBar.addVetoableChangeListener(new VetoableChangeListener() {
   public void vetoableChange(PropertyChangeEvent arg0) {
    
   }
  });
  scrollBar.addPropertyChangeListener(new PropertyChangeListener() {
   public void propertyChange(PropertyChangeEvent arg0) {
    
   }
  });
  scrollBar.setBounds(31, 507, 709, 16);
  contentPane.add(scrollBar);
  
  textField = new JTextField();
  textField.setEditable(false);
  textField.setHorizontalAlignment(SwingConstants.CENTER);
  textField.setBounds(682, 473, 61, 28);
  contentPane.add(textField);
  textField.setColumns(10);
  
  chckbxNewCheckBox = new JCheckBox("Keep Playing");
  chckbxNewCheckBox.addActionListener(new ActionListener() {
   public void actionPerformed(ActionEvent arg0) {
    if(chckbxNewCheckBox.isSelected()) {
     keepPlaying = true;
    } else {
     keepPlaying = false;
    }
   }
  });
  chckbxNewCheckBox.setHorizontalAlignment(SwingConstants.CENTER);
  chckbxNewCheckBox.setBounds(601, 422, 117, 23);
  contentPane.add(chckbxNewCheckBox);
  
  scrollBar.setValue(Integer.parseInt(getVolume()));
  textField.setText(getVolume());
 }

 @Override
 public synchronized void _play() {
  
  System.out.println("_play() : Request to play the choosen song in the playlist...");
  
  // TODO Auto-generated method stub
  if(list.getItemCount() == 0) {
   return;
  }
  try
  {
     
   System.out.println("@ Play message received...");
   
   int selectedIndex = list.getSelectedIndex();
   System.out.println("Selected index: " + selectedIndex);
   
   String fileToPlay = allSongsLinkedList.get(selectedIndex);
   System.out.println("fileToPlay: " + fileToPlay);
   
   String playCommand = "PlayFile " + fileToPlay;
   System.out.println("Play Command: " + playCommand);
   
   String cmd[] = {"PlayFile", fileToPlay}; 
   
   new Thread(new CommandRunnerTest(cmd),"Command Runner").start();
   //CR.setCmdToRun(cmd);
   //CR.EXECUTE();
      
   
   CurrentPlayerState = PlayerState.PLAYING;
   
  }
  catch (Exception e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
 }

 @Override
 public synchronized void _stop() {
  System.out.println("_stop() : Stop message received...");
  // TODO Auto-generated method stub
  if(list.getItemCount() == 0) {
   return;
  }
  
  String[] killCmd = {"killall" ,"-9", "PlayFile"};
  
  try 
  {
   Process pKill = Runtime.getRuntime().exec(killCmd);
   pKill.waitFor();
  } catch(Exception e) {
   e.printStackTrace();
  }
  
  server_thread.StopServer();
  if(CurrentPlayerState != PlayerState.STOPPED) {
   //CR.stopExecution();
   CurrentPlayerState = PlayerState.STOPPED;
   System.out.println("@ Success ! Stopped !");
  } else {
   System.out.println("@ Oops ! Already Stopped !");
  }
  
 }

 @Override
 public synchronized void _exit()  {
  System.out.println("_exit() : Exit message received...");
  // TODO Auto-generated method stub
  if(list.getItemCount() == 0) {
   return;
  } 
  
  //if(CR != null) {
   //CR.stopExecution();
  //}
  
  String[] killCmd = {"killall" ,"-9", "PlayFile"};
  
  try 
  {
   Process pKill = Runtime.getRuntime().exec(killCmd);
   pKill.waitFor();
  } catch(Exception e) {
   e.printStackTrace();
  }
  server_thread.StopServer();
  System.exit(0);
 }

 @Override
 public void _playrandom() {
  System.out.println("_playrandom() : Request to play a random song...");
  // TODO Auto-generated method stub
  if(list.getItemCount() == 0) {
   return;
  }
  Random rand = new Random();
  int totalSizeOfList = allSongsLinkedList.size();
  int randomIndex = rand.nextInt(totalSizeOfList);
  System.out.println("Random index => " + randomIndex);
  playIndex(randomIndex);
  list.select(randomIndex);
  
 }

 @Override
 public void _setvolume(int volume) {
  // TODO Auto-generated method stub
  setVolume(volume);
  textField.setText(Integer.toString(scrollBar.getValue()));
 }
}

Server Code (Java application running on Mac OS X)

8 >> File: Message.java

package com.giri.player;

import java.io.Serializable;

/**
 *
 * @author Janith (http://cyberasylum.wordpress.com/)
 */
public class Message implements Serializable{

    /**
  * 
  */
 private static final long serialVersionUID = 1L;
 
 private String message;

    public Message(String message) {
        this.message = message;
    }

    public String getMessage(){
        return message;
    }
}

Server Code (Java application running on Mac OS X)

9 >> File: MyCalculation.java

package com.giri.player;

public class MyCalculation extends WorkRequest
{
    /**
  * 
  */
 private static final long serialVersionUID = 1L;
 int n;
  
    public MyCalculation( int n )
    {
        this.n = n;
    }
    public Object execute()
    {
        return new Integer( n * n );
    }
}

Server Code (Java application running on Mac OS X)

10 >> File: MyLogger.java

package com.giri.player;


import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.XMLFormatter;

public class MyLogger {
 
 private LogManager lm = null;
    private Logger logger;
    private FileHandler fh = null;
    
    public MyLogger(String className) {
     try {
   fh = new FileHandler("/tmp/player.log");
  } catch (SecurityException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
     lm = LogManager.getLogManager();
     logger = Logger.getLogger(className);
     lm.addLogger(logger);
     logger.setLevel(Level.INFO);
     fh.setFormatter(new XMLFormatter());
     logger.addHandler(fh);
    }        
    
    public void LOG(String msg) {
     logger.log(Level.INFO, msg);
    }
    
    public void DONE() {
     fh.close();
    }
}

Server Code (Java application running on Mac OS X)

11 >> File: MySong.java

package com.giri.player;

public class MySong extends SongRequest {
 
 private static final long serialVersionUID = 1L;
 
 int index = 0;
 
 public MySong(int n) {
  index = n;
 }

 @Override
 public Object execute() {
  // TODO Auto-generated method stub
  MainWindow.PLAY(index);
  return null;
 }

}

Server Code (Java application running on Mac OS X)

12 >> File: NewClient.java

package com.giri.player;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;

public class NewClient {

    private  final String SERVER_IP = "127.0.0.1";
    private  final int SERVER_PORT = 1122;

    public void MainMethod(String args)
    {

        Socket socket = null;
        AllSongsObject aso = null;
        
        try
        {
            socket = new Socket(SERVER_IP, SERVER_PORT);
            System.out.println("# Client # : Connected to server!");
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
         System.out.println("# Client # : Error connecting to server: " + ex.getMessage());
        }

        ObjectInputStream in = null;
        ObjectOutputStream out = null;

 
        try
        {
    
            out = new ObjectOutputStream(socket.getOutputStream());

            //read a string
            
            System.out.println("# Client # : Message entered is: " + args);

            //send it to server
            out.writeObject(new Message(args));
            out.flush();
            
            System.out.println("# Client # : Reading from input stream...");
      
            in = new ObjectInputStream(socket.getInputStream());
            
            aso = (AllSongsObject) in.readObject();
            
            System.out.println("# Client # : Server returned object of size: " + aso.get_ll().size());
            
            System.out.println("# Client # : Contents of the list: ");
            
            for(int i=0; i<aso.get_ll().size(); i++) {
             System.out.println(aso.get_ll().get(i));
            }

        }
        catch (Exception ex)
        {
         ex.printStackTrace();
            System.out.println("# Client # : Error: " + ex);
        }
        finally
        {
         try 
         {
             out.close();
             socket.close();
         } catch(Exception e)
         {
          e.printStackTrace();
         }
        }
    }
    /*
    public static void main(String[] args)
    {
     new NewClient().MainMethod("giri");
    }
    */
    
}

Server Code (Java application running on Mac OS X)

13 >> File: NewServer.java

package com.giri.player;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.Random;

/**
 *
 * @author Janith (http://cyberasylum.wordpress.com/)
 */
public class NewServer extends Thread {
 
    private final int PORT = 8081;

    private String myString = null;
    
    private static ServerSocket serverSocket = null;
    private static Socket socket = null;
    
    private Message message = null;
    
    public NewServer(String mystr) {
     myString = mystr;
    }
    
    public void StartServer() {
     
     String args = myString; 
     
     AllSongsObject aso = new AllSongsObject(MainWindow.allSongsFileNamesOnly);
     
     try
        {
            serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(PORT));
        }
        catch (Exception ex)
        {
         ex.printStackTrace();
            System.out.println("# Server # : Error occured while creating the server socket");
            return;
        }
             
        while (true)
        {
            try
            {
            
                socket = serverSocket.accept();
                                          
                //Now we have established the a connection with the client
                
                System.out.println("# Server # : Connection created, client IP: " + socket.getInetAddress());
                
                ObjectInputStream in = null;
                ObjectOutputStream out = null;
       
                in = new ObjectInputStream(socket.getInputStream());
                
                 message = (Message) in.readObject();
                
                System.out.println("# Server # : Client said: " + message.getMessage());
                
                if(message.getMessage().equals(Constants.GETPLAYLIST))
                {
                 out = new ObjectOutputStream(socket.getOutputStream());
                    out.writeObject(aso);
                    out.flush();
               
                }
                else if(message.getMessage().contains(Constants.PLAYINDEX))
                {
                 String[] cmd = message.getMessage().split("@");
                 String indexStr = cmd[1];
                 int index = Integer.parseInt(indexStr);
                 MainWindow.PLAY(index);
                 
                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object)null);
                 out.flush();
                }
                else if(message.getMessage().contains(Constants.LOOP)) {
                 MainWindow.chckbxNewCheckBox.setSelected(true);
                 MainWindow.keepPlaying = true;
                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object)null);
                 out.flush();
                } else if(message.getMessage().contains(Constants.DONTLOOP)) {
                 MainWindow.chckbxNewCheckBox.setSelected(false);
                 MainWindow.keepPlaying = false;
                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object)null);
                 out.flush();
                } else if(message.getMessage().contains(Constants.GETVOLUME)) {
                 String strVolume = MainWindow.getVolume();
                 int vol = Integer.parseInt(strVolume);
                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object) vol);
                 out.flush();
                } else if(message.getMessage().contains(Constants.SETVOLUME)) {
                 String[] cmd = message.getMessage().split("@");
                 String volumeStr = cmd[1];
                 MainWindow.setVolume(Integer.parseInt(volumeStr));
                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object)null);
                 out.flush();
                } else if(message.getMessage().contains(Constants.PLAYRANDOM)) {
                 
                 int size = MainWindow.allSongsLinkedList.size();
                 
                 if(size>0) {
                  Random rand = new Random();
                  int randomIndex = rand.nextInt(size);
                  MainWindow.PLAY(randomIndex);
                 }

                 out = new ObjectOutputStream(socket.getOutputStream());
                 out.writeObject((Object)null);
                 out.flush();
                }
            }
            
            catch (Exception ex)
            {
             ex.printStackTrace();
                System.out.println("# Server # : Error: " + ex.getMessage());
                
                //try {
                // socket.close();
                // serverSocket.close();
                //} catch(Exception e) {
                // System.out.println("Error in closing the sockets ... " + e.getMessage());
                //}
            }
            
            try {
    Thread.currentThread().sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
        } // while (true)
    }
 @Override
 public void run() {
  // TODO Auto-generated method stub
  super.run();
  StartServer();
 }
    
 public void StopServer() {
  try {
   if(!socket.isClosed()) {
    socket.close();
   }
   if(!serverSocket.isClosed()) {
    serverSocket.close();
   }
  } catch(Exception e) {
   System.out.println("Error in shutting down the server ... " + e.getMessage());
  }
 }
    
}

Server Code (Java application running on Mac OS X)

14 >> File: PlayerState.java


package com.giri.player;

public enum PlayerState {
 PLAYING,
 STOPPED,
 PAUSED,
 STOP,
 PLAY,
 
 RESUMED,
 PAUSE,
 RESUME
}

Server Code (Java application running on Mac OS X)

15 >> File: ProcessMonitor.java

package com.giri.player;

import java.util.Random;

public class ProcessMonitor implements Runnable {

 public void run() {
  System.out.println("$$ Starting process monitor...");
  // TODO Auto-generated method stub
   
  while(true) {
   // System.out.println(">> ProcessMonitor >> CommandRunnerTest.retCode = " + CommandRunnerTest.retCode);
   /*
   if(CommandRunnerTest.retCode == -1) {
    break;
   }
   */
   
   //System.out.println("# Volume fetched via apple script => " + MainWindow.getVolume());
   
   if(CommandRunnerTest.retCode == 0 )
   {
    //System.out.println(">> ProcessMonitor >>retCode = 0 !");
    
    if(MainWindow.keepPlaying)
    {
     //System.out.println(">> ProcessMonitor >> keepPlaying = True");
     //System.out.println("$$ Exit Code == 0 ! Doing a replay() ! ...");
     
     // TODO Auto-generated method stub
     if(MainWindow.allSongsLinkedList.size() == 0) {
      return;
     }
     
     Random rand = new Random();
     int totalSizeOfList = MainWindow.allSongsLinkedList.size();
     int randomIndex = rand.nextInt(totalSizeOfList);
     
     System.out.println("Random index => " + randomIndex);
        
     
     MainWindow.PLAY(randomIndex);
     CommandRunnerTest.retCode = -1;
    }
   } 
   
   try {
    Thread.currentThread().sleep(1000);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }

}

Server Code (Java application running on Mac OS X)

16 >> File: Server.java

package com.giri.player;

//file: Server.java
import java.net.*;
import java.io.*;

public class Server {
 

 public void startServer(String args)
 {
 
  ServerSocket ss = null;
  try
  {
   System.out.println("# Creating new socket ...");
   ss = new ServerSocket(Integer.parseInt(args));
  }
  catch (NumberFormatException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  while (true)
  {
   try
   {
    System.out.println("# Starting server side connection ...");
    new ServerConnection(ss.accept()).start();
   }
   catch (SocketException e)
   {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   catch (IOException e)
   {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
  }
 }
 
 /*public static void main(String argv[]) throws IOException {
  ServerSocket ss = new ServerSocket(Integer.parseInt(argv[0]));
  while (true)
   new ServerConnection(ss.accept()).start();
 }*/
 
} // end of class Server

Server Code (Java application running on Mac OS X)

17 >> File: SongRequest.java

package com.giri.player;

public abstract class SongRequest extends Request {
 
 private static final long serialVersionUID = 1L;
 public abstract Object execute();
}

Server Code (Java application running on Mac OS X)

18 >> File: WorkRequest.java

package com.giri.player;

public abstract class WorkRequest extends Request {
    /**
  * 
  */
 private static final long serialVersionUID = 1L;

 public abstract Object execute( );
}

19 >> Server Code (Java application running on Mac OS X)

File: PlayFile.java - Compiling this gives the binary "PlayFile" which is actually run my the server side to play a file

/* Copyright � 2007 Apple Inc. All Rights Reserved.
 
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by 
   Apple Inc. ("Apple") in consideration of your agreement to the
   following terms, and your use, installation, modification or
   redistribution of this Apple software constitutes acceptance of these
   terms.  If you do not agree with these terms, please do not use,
   install, modify or redistribute this Apple software.
   
   In consideration of your agreement to abide by the following terms, and
   subject to these terms, Apple grants you a personal, non-exclusive
   license, under Apple's copyrights in this original Apple software (the
   "Apple Software"), to use, reproduce, modify and redistribute the Apple
   Software, with or without modifications, in source and/or binary forms;
   provided that if you redistribute the Apple Software in its entirety and
   without modifications, you must retain this notice and the following
   text and disclaimers in all such redistributions of the Apple Software. 
   Neither the name, trademarks, service marks or logos of Apple Inc. 
   may be used to endorse or promote products derived from the Apple
   Software without specific prior written permission from Apple.  Except
   as expressly stated in this notice, no other rights or licenses, express
   or implied, are granted by Apple herein, including but not limited to
   any patent rights that may be infringed by your derivative works or by
   other works in which the Apple Software may be incorporated.
   
   The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
   MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
   THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
   FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
   OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
   
   IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
   OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
   MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
   AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
   STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE.
*/
#include 
#include "CAXException.h"
#include "CAStreamBasicDescription.h"
#include "CAAudioUnit.h"

void UsageString(int exitCode)
{
 printf ("Usage: PlayFile /path/to/file\n");
 exit(exitCode);
}

// helper functions
double PrepareFileAU (CAAudioUnit &au, CAStreamBasicDescription &fileFormat, AudioFileID audioFile);
void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile);


int main (int argc, char * const argv[]) 
{
 if (argc < 2) UsageString(1);

 AudioFileID audioFile;
 
 const char* inputFile = argv[1];

 CFURLRef theURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (UInt8*)inputFile, strlen(inputFile), false);
    XThrowIfError (!theURL, "CFURLCreateFromFileSystemRepresentation");
 
    OSStatus err = AudioFileOpenURL (theURL, kAudioFileReadPermission, 0, &audioFile);
    CFRelease(theURL);
 XThrowIfError (err, "AudioFileOpenURL");
   
   // get the number of channels of the file
 CAStreamBasicDescription fileFormat;
 UInt32 propsize = sizeof(CAStreamBasicDescription);
 XThrowIfError (AudioFileGetProperty(audioFile, kAudioFilePropertyDataFormat, &propsize, &fileFormat), "AudioFileGetProperty");
 
 printf ("playing file: %s\n", inputFile);
 printf ("format: "); fileFormat.Print();


// lets set up our playing state now
 AUGraph theGraph;
 CAAudioUnit fileAU;

// this makes the graph, the file AU and sets it all up for playing
 MakeSimpleGraph (theGraph, fileAU, fileFormat, audioFile);
  

// now we load the file contents up for playback before we start playing
// this has to be done the AU is initialized and anytime it is reset or uninitialized
 Float64 fileDuration = PrepareFileAU (fileAU, fileFormat, audioFile);
  printf ("file duration: %f secs\n", fileDuration);

// start playing
 XThrowIfError (AUGraphStart (theGraph), "AUGraphStart");
 
// sleep until the file is finished
 usleep ((int)(fileDuration * 1000. * 1000.));

// lets clean up
 XThrowIfError (AUGraphStop (theGraph), "AUGraphStop");
 XThrowIfError (AUGraphUninitialize (theGraph), "AUGraphUninitialize");
 XThrowIfError (AudioFileClose (audioFile), "AudioFileClose");
 XThrowIfError (AUGraphClose (theGraph), "AUGraphClose");
 
 return 0;
} 

double PrepareFileAU (CAAudioUnit &au, CAStreamBasicDescription &fileFormat, AudioFileID audioFile)
{ 
// 
  // calculate the duration
 UInt64 nPackets;
 UInt32 propsize = sizeof(nPackets);
 XThrowIfError (AudioFileGetProperty(audioFile, kAudioFilePropertyAudioDataPacketCount, &propsize, &nPackets), "kAudioFilePropertyAudioDataPacketCount");
  
 Float64 fileDuration = (nPackets * fileFormat.mFramesPerPacket) / fileFormat.mSampleRate;

 ScheduledAudioFileRegion rgn;
 memset (&rgn.mTimeStamp, 0, sizeof(rgn.mTimeStamp));
 rgn.mTimeStamp.mFlags = kAudioTimeStampSampleTimeValid;
 rgn.mTimeStamp.mSampleTime = 0;
 rgn.mCompletionProc = NULL;
 rgn.mCompletionProcUserData = NULL;
 rgn.mAudioFile = audioFile;
 rgn.mLoopCount = 1;
 rgn.mStartFrame = 0;
 rgn.mFramesToPlay = UInt32(nPackets * fileFormat.mFramesPerPacket);
  
  // tell the file player AU to play all of the file
 XThrowIfError (au.SetProperty (kAudioUnitProperty_ScheduledFileRegion, 
   kAudioUnitScope_Global, 0,&rgn, sizeof(rgn)), "kAudioUnitProperty_ScheduledFileRegion");
 
  // prime the fp AU with default values
 UInt32 defaultVal = 0;
 XThrowIfError (au.SetProperty (kAudioUnitProperty_ScheduledFilePrime, 
   kAudioUnitScope_Global, 0, &defaultVal, sizeof(defaultVal)), "kAudioUnitProperty_ScheduledFilePrime");

  // tell the fp AU when to start playing (this ts is in the AU's render time stamps; -1 means next render cycle)
 AudioTimeStamp startTime;
 memset (&startTime, 0, sizeof(startTime));
 startTime.mFlags = kAudioTimeStampSampleTimeValid;
 startTime.mSampleTime = -1;
 XThrowIfError (au.SetProperty(kAudioUnitProperty_ScheduleStartTimeStamp, 
   kAudioUnitScope_Global, 0, &startTime, sizeof(startTime)), "kAudioUnitProperty_ScheduleStartTimeStamp");

 return fileDuration;
}



void MakeSimpleGraph (AUGraph &theGraph, CAAudioUnit &fileAU, CAStreamBasicDescription &fileFormat, AudioFileID audioFile)
{
 XThrowIfError (NewAUGraph (&theGraph), "NewAUGraph");
 
 CAComponentDescription cd;

 // output node
 cd.componentType = kAudioUnitType_Output;
 cd.componentSubType = kAudioUnitSubType_DefaultOutput;
 cd.componentManufacturer = kAudioUnitManufacturer_Apple;


 AUNode outputNode;
 XThrowIfError (AUGraphAddNode (theGraph, &cd, &outputNode), "AUGraphAddNode");
 
 // file AU node
 AUNode fileNode;
 cd.componentType = kAudioUnitType_Generator;
 cd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
 
 XThrowIfError (AUGraphAddNode (theGraph, &cd, &fileNode), "AUGraphAddNode");
 
 // connect & setup
 XThrowIfError (AUGraphOpen (theGraph), "AUGraphOpen");
 
 // install overload listener to detect when something is wrong
 AudioUnit anAU;
 XThrowIfError (AUGraphNodeInfo(theGraph, fileNode, NULL, &anAU), "AUGraphNodeInfo");
 
 fileAU = CAAudioUnit (fileNode, anAU);

// prepare the file AU for playback
// set its output channels
 XThrowIfError (fileAU.SetNumberChannels (kAudioUnitScope_Output, 0, fileFormat.NumberChannels()), "SetNumberChannels");

// set the output sample rate of the file AU to be the same as the file:
 XThrowIfError (fileAU.SetSampleRate (kAudioUnitScope_Output, 0, fileFormat.mSampleRate), "SetSampleRate");

// load in the file 
 XThrowIfError (fileAU.SetProperty(kAudioUnitProperty_ScheduledFileIDs, 
      kAudioUnitScope_Global, 0, &audioFile, sizeof(audioFile)), "SetScheduleFile");


 XThrowIfError (AUGraphConnectNodeInput (theGraph, fileNode, 0, outputNode, 0), "AUGraphConnectNodeInput");

// AT this point we make sure we have the file player AU initialized
// this also propogates the output format of the AU to the output unit
 XThrowIfError (AUGraphInitialize (theGraph), "AUGraphInitialize");
 
 // workaround a race condition in the file player AU
 usleep (10 * 1000);

// if we have a surround file, then we should try to tell the output AU what the order of the channels will be
 if (fileFormat.NumberChannels() > 2) {
  UInt32 layoutSize = 0;
  OSStatus err;
  XThrowIfError (err = AudioFileGetPropertyInfo (audioFile, kAudioFilePropertyChannelLayout, &layoutSize, NULL),
        "kAudioFilePropertyChannelLayout");
  
  if (!err && layoutSize) {
   char* layout = new char[layoutSize];
   
   err = AudioFileGetProperty(audioFile, kAudioFilePropertyChannelLayout, &layoutSize, layout);
   XThrowIfError (err, "Get Layout From AudioFile");
   
   // ok, now get the output AU and set its layout
   XThrowIfError (AUGraphNodeInfo(theGraph, outputNode, NULL, &anAU), "AUGraphNodeInfo");
   
   err = AudioUnitSetProperty (anAU, kAudioUnitProperty_AudioChannelLayout, 
       kAudioUnitScope_Input, 0, layout, layoutSize);
   XThrowIfError (err, "kAudioUnitProperty_AudioChannelLayout");
   
   delete [] layout;
  }
 }
}

No comments :

Post a Comment