2011-03-25

aidl file of Winamp

I've been experimenting adding support for Winamp in my application that is supposed to be released soon.   But the first thing I need to consider is a correct Android interface file that describes the interface Winamp's music service has. After several trial&error, I have some findings,

  1. Winamp uses built-in MediaStore provider.
    • Playlists created in built-in Music application can be seen in Winamp and playlists created from Winamp can be seen in built-in Music application.
  2. Winamp uses built-in IMediaPlaybackService.aidl which package names replaced with com.nullsoft.winamp. Still, it changes some code that makes my integration difficult. Here are my steps to guess its aidl interface,
    • Installed Winamp in a rooted device and debug it.
    • Because Winamp doesn't obfuscate its code, we can use Java's reflection to see its class and method interfaces easily. In jdb,
      • Run 'classes' to see all classes started with com.nullsoft.winamp. You can see one line for com.nullsoft.winamp.IMediaPlaybackService
      • Run 'methods com.nullsoft.winamp.IMediaPlaybackService' to list all method declaration of this class. You can see it not having differences than standard IMediaPlaybackService.
      • com.nullsoft.winamp.IMediaPlaybackService duration()
        com.nullsoft.winamp.IMediaPlaybackService enqueue(long[], int)
        com.nullsoft.winamp.IMediaPlaybackService getAlbumId()
        com.nullsoft.winamp.IMediaPlaybackService getAlbumName()
        com.nullsoft.winamp.IMediaPlaybackService getArtistId()
        com.nullsoft.winamp.IMediaPlaybackService getArtistName()
        com.nullsoft.winamp.IMediaPlaybackService getAudioId()
        com.nullsoft.winamp.IMediaPlaybackService getMediaMountedCount()
        com.nullsoft.winamp.IMediaPlaybackService getPath()
        com.nullsoft.winamp.IMediaPlaybackService getQueue()
        com.nullsoft.winamp.IMediaPlaybackService getQueueLen()
        com.nullsoft.winamp.IMediaPlaybackService getQueuePosition()
        com.nullsoft.winamp.IMediaPlaybackService getRepeatMode()
        com.nullsoft.winamp.IMediaPlaybackService getShuffleMode()
        com.nullsoft.winamp.IMediaPlaybackService getTrackName()
        com.nullsoft.winamp.IMediaPlaybackService isPlaying()
        com.nullsoft.winamp.IMediaPlaybackService moveQueueItem(int, int)
        com.nullsoft.winamp.IMediaPlaybackService next()
        com.nullsoft.winamp.IMediaPlaybackService open(long[], int)
        com.nullsoft.winamp.IMediaPlaybackService openFile(java.lang.String, boolean)
        com.nullsoft.winamp.IMediaPlaybackService openFileAsync(java.lang.String)
        com.nullsoft.winamp.IMediaPlaybackService pause()
        com.nullsoft.winamp.IMediaPlaybackService play()
        com.nullsoft.winamp.IMediaPlaybackService position()
        com.nullsoft.winamp.IMediaPlaybackService prev()
        com.nullsoft.winamp.IMediaPlaybackService quit()
        com.nullsoft.winamp.IMediaPlaybackService removeTrack(long)
        com.nullsoft.winamp.IMediaPlaybackService removeTracks(int, int)
        com.nullsoft.winamp.IMediaPlaybackService seek(long)
        com.nullsoft.winamp.IMediaPlaybackService setQueuePosition(int)
        com.nullsoft.winamp.IMediaPlaybackService setRepeatMode(int)
        com.nullsoft.winamp.IMediaPlaybackService setShuffleMode(int)
        com.nullsoft.winamp.IMediaPlaybackService stop()
        
    • Duplicate IMediaPlaybackService.aidl from built-in Music code and replace its package name, include this file in your project.
    • Although the code builds successfully, it doesn't work as expected.
      public void onServiceConnected(ComponentName name, IBinder binder) {
          com.nullsoft.winamp.IMediaPlaybackService s = com.nullsoft.winamp.IMediaPlaybackService.Stub.asInterface(binder);
          try {
              // s.isPlaying() and s.top() are working.
              if (s.isPlaying()) {
                  s.stop();
              }
      
              // s.open() broadcasts com.nullsoft.winamp.queuechanged if audio ids
              // are set successfully. 
              s.open(mData, 0);
      
              /* s.next() works but only plays one song and causes 
                 com.nullsoft.winamp.playstatechanged and com.nullsoft.winamp.metachanged
                 broadcasted. */ 
              s.next();
      
              /* s.play() doesn't work. Guess that MediaPlayer is not initialized if Winamp doesn't 
                 change too much from standard Music */
              // s.play();
          } catch (RemoteException e) {
          }
      }
      
    • I should do more experiments to guess how it responds to different parameters and modes.
This process (reverse engineering) is normally what authors of an application don't want people do on their applications.

OBFUSCATE YOUR APPLICATION IF YOU DO MIND.