]> git.sesse.net Git - vlc/blobdiff - modules/gui/beos/VlcWrapper.cpp
* use var_Set/Get "state"/"position"/"rate" instead of old functions.
[vlc] / modules / gui / beos / VlcWrapper.cpp
index d161b83d4d210d5920a80d70b5a10b8877dba6f2..299901eb90e244b9bb99681a4964108e157be91a 100644 (file)
@@ -2,7 +2,7 @@
  * VlcWrapper.cpp: BeOS plugin for vlc (derived from MacOS X port)
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: VlcWrapper.cpp,v 1.14 2002/12/26 18:17:38 stippi Exp $
+ * $Id$
  *
  * Authors: Florian G. Pflug <fgp@phlo.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
  * along with this program{} if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
+#include <AppKit.h>
+#include <InterfaceKit.h>
 #include <SupportKit.h>
 
 #include <vlc/vlc.h>
 #include <vlc/intf.h>
-extern "C" {
-#include <audio_output.h>
-#include <aout_internal.h>
+#include <vlc/vout.h>
+extern "C"
+{
+  #include <input_ext-plugins.h> // needed here when compiling without plugins
+  #include <audio_output.h>
+  #include <aout_internal.h>
 }
 
 #include "VlcWrapper.h"
+#include "MsgVals.h"
+
+const char * _AddEllipsis( char * string )
+{
+    char * temp;
+    temp = (char*) calloc( strlen( string ) + 4, 1 );
+    sprintf( temp, "%s%s", string, B_UTF8_ELLIPSIS );
+    return temp;
+}
 
 /* constructor */
 VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
 {
     p_intf = p_interface;
     p_input = NULL;
-    p_aout = NULL;
     p_playlist = (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                 FIND_ANYWHERE );
 }
@@ -49,50 +62,25 @@ VlcWrapper::VlcWrapper( intf_thread_t *p_interface )
 VlcWrapper::~VlcWrapper()
 {
     if( p_input )
-    {
         vlc_object_release( p_input );
-    }
+
     if( p_playlist )
-    {
         vlc_object_release( p_playlist );
-    }
-    if( p_aout )
-    {
-        vlc_object_release( p_aout );
-    }
 }
 
-/* UpdateInputAndAOut: updates p_input and p_aout, returns true if the
-   interface needs to be updated */
-bool VlcWrapper::UpdateInputAndAOut()
+/* UpdateInput: updates p_input */
+void VlcWrapper::UpdateInput()
 {
-    if( p_input == NULL )
-    {
+    if( !p_input )
         p_input = (input_thread_t *)vlc_object_find( p_intf, VLC_OBJECT_INPUT,
                                                      FIND_ANYWHERE );
-    }
-    if( p_aout == NULL )
-    {
-        p_aout = (aout_instance_t*)vlc_object_find( p_intf, VLC_OBJECT_AOUT,
-                                                    FIND_ANYWHERE );
-    }
         
-    if( p_input != NULL )
-    {
+    if( p_input )
         if( p_input->b_dead )
         {
             vlc_object_release( p_input );
             p_input = NULL;
-            
-            if( p_aout )
-            {
-                vlc_object_release( p_aout );
-                p_aout = NULL;
-            }
         }
-        return true;
-    }
-    return false;
 }
 
 
@@ -100,15 +88,21 @@ bool VlcWrapper::UpdateInputAndAOut()
  * input infos and control *
  ***************************/
 
-/* status (UNDEF_S, PLAYING_S, PAUSE_S, FORWARD_S, BACKWARD_S,
-   REWIND_S, NOT_STARTED_S, START_S) */
+bool VlcWrapper::HasInput()
+{
+    return ( p_input != NULL );
+}
+
 int VlcWrapper::InputStatus()
 {
     if( !p_input )
     {
         return UNDEF_S;
     }
-    return p_input->stream.control.i_status;
+    
+    vlc_value_t state;
+    var_Get( p_input, "state", &state );
+    return state.i_int;
 }
 
 int VlcWrapper::InputRate()
@@ -117,196 +111,221 @@ int VlcWrapper::InputRate()
     {
         return DEFAULT_RATE;
     }
+    
     return p_input->stream.control.i_rate;
 }
 
-/* tell: location in the current stream (in arbitrary units) */
-int VlcWrapper::InputTell()
+void VlcWrapper::InputSetRate( int rate )
 {
     if( !p_input )
     {
-        return -1;
+        return;
     }
-    return p_input->stream.p_selected_area->i_tell;
+    var_SetInteger( p_input, "rate", rate );
 }
 
-/* size: total size of the current stream (in arbitrary units) */
-int VlcWrapper::InputSize()
+BList * VlcWrapper::GetChannels( int i_cat )
 {
-    if( !p_input )
-    {
-        return -1;
-    }
-    return p_input->stream.p_selected_area->i_size;
-}
-
-void VlcWrapper::InputSlower()
-{
-    if( p_input != NULL )
+    if( p_input )
     {
-        input_SetStatus( p_input, INPUT_STATUS_SLOWER );
-    }
-    //VolumeMute();
-}
+        unsigned int i;
+        uint32 what;
+        const char* fieldName;
 
-void VlcWrapper::InputFaster()
-{
-    if( p_input != NULL )
-    {
-        input_SetStatus( p_input, INPUT_STATUS_FASTER );
-    }
-    //VolumeMute();
-}
+        switch( i_cat )
+        {
+            case AUDIO_ES:
+            {
+                what = SELECT_CHANNEL;
+                fieldName = "channel";
+                break;
+            }
+            case SPU_ES:
+            {
+                what = SELECT_SUBTITLE;
+                fieldName = "subtitle";
+                break;
+            }
+            default:
+            return NULL;
+       }
 
-void VlcWrapper::openFiles( BList* o_files, bool replace )
-{
-    BString *o_file;
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+      
+        /* find which track is currently playing */
+        es_descriptor_t *p_es = NULL;
+        for( i = 0; i < p_input->stream.i_selected_es_number; i++ )
+        {
+            if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
+                p_es = p_input->stream.pp_selected_es[i];
+        }
+        
+        /* build a list of all tracks */
+        BList *list = new BList( p_input->stream.i_es_number );
+        BMenuItem *menuItem;
+        BMessage *message;
+        char *trackName;
+        
+        /* "None" */
+        message = new BMessage( what );
+        message->AddInt32( fieldName, -1 );
+        menuItem = new BMenuItem( _("None"), message );
+        if( !p_es )
+            menuItem->SetMarked( true );
+        list->AddItem( menuItem );
+        
+        for( i = 0; i < p_input->stream.i_es_number; i++ )
+        {
+            if( p_input->stream.pp_es[i]->i_cat == i_cat )
+            {
+                message = new BMessage( what );
+                message->AddInt32( fieldName, i );
+                if( !p_input->stream.pp_es[i]->psz_desc ||
+                    !*p_input->stream.pp_es[i]->psz_desc )
+                    trackName = _("<unknown>");
+                else
+                    trackName = strdup( p_input->stream.pp_es[i]->psz_desc );
+                menuItem = new BMenuItem( trackName, message );
+                if( p_input->stream.pp_es[i] == p_es )
+                    menuItem->SetMarked( true );
+                list->AddItem( menuItem );
+            }
+        }
+        
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
 
-    while( ( o_file = (BString *)o_files->LastItem() ) )
-    {
-        o_files->RemoveItem(o_files->CountItems() - 1);
-        playlist_Add( p_playlist, o_file->String(),
-                  PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
-        delete o_file;
+        return list;
     }
+    return NULL;
 }
 
-void VlcWrapper::openDisc(BString o_type, BString o_device, int i_title, int i_chapter)
+void VlcWrapper::ToggleLanguage( int i_language )
 {
-    BString o_source("");
-    o_source << o_type << ":" << o_device ;
-
-    playlist_Add( p_playlist, o_source.String(),
-                  PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
-}
-
-
-
-void VlcWrapper::toggleLanguage(int i_language)
-{
-
-    int32 i_old = -1;
-    int i_cat = AUDIO_ES;
+    es_descriptor_t * p_es = NULL;
+    es_descriptor_t * p_es_old = NULL;
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
     {
-        if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
+        if( p_input->stream.pp_selected_es[i]->i_cat == AUDIO_ES )
         {
-            i_old = i;
+            p_es_old = p_input->stream.pp_selected_es[i];
             break;
         }
     }
     vlc_mutex_unlock( &p_input->stream.stream_lock );
-
-    msg_Info( p_intf, "Old: %d,  New: %d", i_old, i_language);
+    
     if( i_language != -1 )
     {
-        input_ToggleES( p_input, 
-                        p_input->stream.pp_selected_es[i_language],
-                        VLC_TRUE );
+        p_es = p_input->stream.pp_es[i_language];
     }
-
-    if( (i_old != -1) && (i_old != i_language) )
+    if( p_es == p_es_old )
+    {
+        return;
+    }
+    if( p_es_old )
+    {
+        input_ToggleES( p_input, p_es_old, VLC_FALSE );
+    }
+    if( p_es )
     {
-        input_ToggleES( p_input, 
-                        p_input->stream.pp_selected_es[i_old],
-                        VLC_FALSE );
+        input_ToggleES( p_input, p_es, VLC_TRUE );
     }
 }
 
-void VlcWrapper::toggleSubtitle(int i_subtitle)
+void VlcWrapper::ToggleSubtitle( int i_subtitle )
 {
-    int32 i_old = -1;
-    int i_cat = SPU_ES;
+    es_descriptor_t * p_es = NULL;
+    es_descriptor_t * p_es_old = NULL;
 
     vlc_mutex_lock( &p_input->stream.stream_lock );
     for( unsigned int i = 0; i < p_input->stream.i_selected_es_number ; i++ )
     {
-        if( p_input->stream.pp_selected_es[i]->i_cat == i_cat )
+        if( p_input->stream.pp_selected_es[i]->i_cat == SPU_ES )
         {
-            i_old = i;
+            p_es_old = p_input->stream.pp_selected_es[i];
             break;
         }
     }
     vlc_mutex_unlock( &p_input->stream.stream_lock );
     
-    msg_Info( p_intf, "Old: %d,  New: %d", i_old, i_subtitle);
     if( i_subtitle != -1 )
     {
-        input_ToggleES( p_input, 
-                        p_input->stream.pp_selected_es[i_subtitle],
-                        VLC_TRUE );
+        p_es = p_input->stream.pp_es[i_subtitle];
     }
-
-    if( (i_old != -1) && (i_old != i_subtitle) )
+    if( p_es == p_es_old )
+    {
+        return;
+    }
+    if( p_es_old )
+    {
+        input_ToggleES( p_input, p_es_old, VLC_FALSE );
+    }
+    if( p_es )
     {
-        input_ToggleES( p_input, 
-                        p_input->stream.pp_selected_es[i_old],
-                        VLC_FALSE );
+        input_ToggleES( p_input, p_es, VLC_TRUE );
     }
 }
 
-const char*  VlcWrapper::getTimeAsString()
+const char * VlcWrapper::GetTimeAsString()
 {
-    static char psz_currenttime[ OFFSETTOTIME_MAX_SIZE ];
+    static char psz_time[ MSTRTIME_MAX_SIZE ];
         
-    if( p_input == NULL )
+    if( !p_input )
     {
         return ("-:--:--");
     }     
    
-    input_OffsetToTime( p_input, 
-                        psz_currenttime, 
-                        p_input->stream.p_selected_area->i_tell );        
+    vlc_value_t time;
+    var_Get( p_input, "time", &time );
+    
+    mtime_t seconds = time.i_time / 1000000;
+    sprintf( psz_time, "%d:%02d:%02d",
+             (int) ( seconds / (60 * 60 ) ),
+             (int) ( ( seconds / 60 ) % 60 ),
+             (int) ( seconds % 60 ) );
 
-    return(psz_currenttime);
+    return psz_time;
 }
 
-float  VlcWrapper::getTimeAsFloat()
+float VlcWrapper::GetTimeAsFloat()
 {
-    float f_time = 0.0;
-
-    if( p_input != NULL )
-    {
-        f_time = (float)p_input->stream.p_selected_area->i_tell / 
-                 (float)p_input->stream.p_selected_area->i_size;
-    }    
-    else
+    if( !p_input )
     {
-        f_time = 0.0;
+        return 0.0;
     }
-    return( f_time );
+    
+    vlc_value_t pos;
+    var_Get( p_input, "position", &pos );
+    return pos.f_float;
 }
 
-void VlcWrapper::setTimeAsFloat(float f_position)
+void VlcWrapper::SetTimeAsFloat( float f_position )
 {
-    if( p_input != NULL )
+    if( !p_input )
     {
-        input_Seek( p_input, 
-                   (long long int)(p_input->stream.p_selected_area->i_size
-                       * f_position / SEEKSLIDER_RANGE ), 
-                   INPUT_SEEK_SET);
+        return;
     }
+    
+    vlc_value_t pos;
+    pos.f_float = f_position / SEEKSLIDER_RANGE;
+    var_Set( p_input, "position", pos );
 }
 
 bool VlcWrapper::IsPlaying()
 {
-
        bool playing = false;
-       if ( p_input )
+       if( p_input )
        {
-               switch ( p_input->stream.control.i_status )
+               switch( p_input->stream.control.i_status )
                {
                        case PLAYING_S:
                        case FORWARD_S:
                        case BACKWARD_S:
-                       case START_S:
                                playing = true;
                    break;
                        case PAUSE_S:
                        case UNDEF_S:
-                       case NOT_STARTED_S:
                        default:
                                break;
                }
@@ -315,9 +334,63 @@ bool VlcWrapper::IsPlaying()
 
 }
 
-/******************************
- * playlist infos and control *
- ******************************/
+/************
+ * playlist *
+ ************/
+
+void VlcWrapper::OpenFiles( BList* o_files, bool replace, int32 index )
+{
+       if ( o_files && o_files->CountItems() > 0)
+       {
+           int size = PlaylistSize();
+               bool wasEmpty = ( size < 1 );
+               if ( index == -1 )
+                       index = PLAYLIST_END;
+               int mode = index == PLAYLIST_END ? PLAYLIST_APPEND : PLAYLIST_INSERT;
+       
+           /* delete current playlist */
+           if( replace )
+           {
+               for( int i = 0; i < size; i++ )
+               {
+                   playlist_Delete( p_playlist, 0 );
+               }
+           }
+       
+           /* insert files */
+           int32 count = o_files->CountItems();
+           for ( int32 i = count - 1; i >= 0; i-- )
+           {
+               if ( BString* o_file = (BString *)o_files->RemoveItem( i ) )
+               {
+                       playlist_Add( p_playlist, o_file->String(),
+                                     o_file->String(), mode, index );
+                       if ( mode == PLAYLIST_INSERT )
+                               index++;
+                       delete o_file;
+               }
+           }
+           // TODO: implement a user setting
+           // if to start automatically
+           /* eventually restart playing */
+           if( replace || wasEmpty )
+           {
+               playlist_Stop( p_playlist );
+               playlist_Play( p_playlist );
+           }
+       }
+}
+void VlcWrapper::OpenDisc(BString o_type, BString o_device, int i_title, int i_chapter)
+{
+    if( config_GetInt( p_intf, "beos-dvdmenus" ) )
+        o_device.Prepend( "dvdplay:" );
+    else
+        o_device.Prepend( "dvdold:" );
+    playlist_Add( p_playlist, o_device.String(), o_device.String(),
+                  PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+}
+
 int VlcWrapper::PlaylistSize()
 {
     vlc_mutex_lock( &p_playlist->object_lock );
@@ -326,9 +399,9 @@ int VlcWrapper::PlaylistSize()
     return i_size;
 }
 
-char *VlcWrapper::PlaylistItemName( int i )
+char * VlcWrapper::PlaylistItemName( int i )
 {
-   return p_playlist->pp_items[i]->psz_name;
+   return p_playlist->pp_items[i]->input.psz_name;
 }
 
 int VlcWrapper::PlaylistCurrent()
@@ -336,17 +409,11 @@ int VlcWrapper::PlaylistCurrent()
     return p_playlist->i_index;
 }
 
-int  VlcWrapper::PlaylistStatus()
-{
-    return p_playlist->i_status;
-}
-
 bool VlcWrapper::PlaylistPlay()
 {
     if( PlaylistSize() )
     {
         playlist_Play( p_playlist );
-        //VolumeRestore();
     }
     return( true );
 }
@@ -355,7 +422,7 @@ void VlcWrapper::PlaylistPause()
 {
     if( p_input )
     {
-        input_SetStatus( p_input, INPUT_STATUS_PAUSE );
+        var_SetInteger( p_input, "state", PAUSE_S );
     }
 }
 
@@ -374,86 +441,30 @@ void VlcWrapper::PlaylistPrev()
     playlist_Prev( p_playlist );
 }
 
-void VlcWrapper::PlaylistSkip( int i )
-{
-    playlist_Skip( p_playlist, i );
-}
-
-void VlcWrapper::PlaylistGoto( int i )
-{
-    playlist_Goto( p_playlist, i );
-}
-
-void VlcWrapper::PlaylistLoop()
-{
-    if ( p_intf->p_sys->b_loop )
-    {
-        playlist_Delete( p_playlist, p_playlist->i_size - 1 );
-    }
-    else
-    {
-        playlist_Add( p_playlist, "vlc:loop",
-                      PLAYLIST_APPEND | PLAYLIST_GO,
-                      PLAYLIST_END );
-    }
-    p_intf->p_sys->b_loop = !p_intf->p_sys->b_loop;
-}
-
-BList * VlcWrapper::PlaylistAsArray()
-{ 
-    int i;
-    BList* p_list = new BList(p_playlist->i_size);
-    
-    vlc_mutex_lock( &p_playlist->object_lock );
-
-    for( i = 0; i < p_playlist->i_size; i++ )
-    {
-        p_list->AddItem(new BString(p_playlist->pp_items[i]->psz_name));
-    }
-
-    vlc_mutex_unlock( &p_playlist->object_lock );
-    return( p_list );
-}
-
-void VlcWrapper::getPlaylistInfo( int32& currentIndex, int32& maxIndex )
+void VlcWrapper::GetPlaylistInfo( int32& currentIndex, int32& maxIndex )
 {
        currentIndex = -1;
        maxIndex = -1;
        if ( p_playlist )
        {
+           vlc_mutex_lock( &p_playlist->object_lock );
+
                maxIndex = p_playlist->i_size;
                if ( maxIndex > 0 )
-                       currentIndex = p_playlist->i_index + 1;
+                       currentIndex = p_playlist->i_index/* + 1 -> why?!?*/;
                else
                        maxIndex = -1;
+
+           vlc_mutex_unlock( &p_playlist->object_lock );
        }
 }
 
-
 void VlcWrapper::PlaylistJumpTo( int pos )
 {
-#if 0
-       // sanity checks
-       if ( pos < 0 )
-               pos = 0;
-       int size = playlistSize();
-       if (pos >= size)
-               pos = size - 1;
-       // weird hack
-    if( p_input_bank->pp_input[0] != NULL )
-               pos--;
-       // stop current stream
-       playlistStop();
-       // modify current position in playlist
-       playlistLock();
-       p_main->p_playlist->i_index = pos;
-       playlistUnlock();
-       // start playing
-       playlistPlay();
-#endif
-}
-
-void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
+    playlist_Goto( p_playlist, pos );
+}
+
+void VlcWrapper::GetNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
 {
        if ( canSkipPrev && canSkipNext )
        {
@@ -497,7 +508,7 @@ void VlcWrapper::getNavCapabilities( bool *canSkipPrev, bool *canSkipNext )
        }
 }
 
-void VlcWrapper::navigatePrev()
+void VlcWrapper::NavigatePrev()
 {
        bool hasSkiped = false;
 
@@ -524,7 +535,7 @@ void VlcWrapper::navigatePrev()
 
                        if ( currentChapter >= 0 )
                        {
-                               toggleChapter( currentChapter );
+                               ToggleChapter( currentChapter );
                                hasSkiped = true;
                        }
                }
@@ -536,7 +547,7 @@ void VlcWrapper::navigatePrev()
                        // disallow area 0 since it is used for video_ts.vob
                        if( currentTitle > 0 )
                        {
-                               toggleTitle(currentTitle);
+                               ToggleTitle(currentTitle);
                                hasSkiped = true;
                        }
                }
@@ -547,7 +558,7 @@ void VlcWrapper::navigatePrev()
                PlaylistPrev();
 }
 
-void VlcWrapper::navigateNext()
+void VlcWrapper::NavigateNext()
 {
        bool hasSkiped = false;
 
@@ -573,7 +584,7 @@ void VlcWrapper::navigateNext()
                        currentChapter++;
                        if ( currentChapter < numChapters )
                        {
-                               toggleChapter( currentChapter );
+                               ToggleChapter( currentChapter );
                                hasSkiped = true;
                        }
                }
@@ -585,7 +596,7 @@ void VlcWrapper::navigateNext()
                        // disallow area 0 since it is used for video_ts.vob
                        if ( currentTitle < numTitles - 1 )
                        {
-                               toggleTitle(currentTitle);
+                               ToggleTitle(currentTitle);
                                hasSkiped = true;
                        }
                }
@@ -596,40 +607,161 @@ void VlcWrapper::navigateNext()
                PlaylistNext();
 }
 
+/*************************
+ * Playlist manipulation *
+ *************************/
 
-/***************************
- * audio infos and control *
- ***************************/
+// PlaylistLock
+bool
+VlcWrapper::PlaylistLock() const
+{
+// TODO: search and destroy -> deadlock!
+return true;
+       if ( p_playlist )
+       {
+               vlc_mutex_lock( &p_playlist->object_lock );
+               return true;
+       }
+       return false;
+}
 
-void VlcWrapper::SetVolume(int value)
+// PlaylistUnlock
+void
+VlcWrapper::PlaylistUnlock() const
 {
-    if( p_aout != NULL )
-    {
-               if ( p_intf->p_sys->b_mute )
+// TODO: search and destroy -> deadlock!
+return;
+       vlc_mutex_unlock( &p_playlist->object_lock );
+}
+
+// PlaylistItemAt
+void*
+VlcWrapper::PlaylistItemAt( int index ) const
+{
+       playlist_item_t* item = NULL;
+       if ( index >= 0 && index < p_playlist->i_size )
+               item = p_playlist->pp_items[index];
+       return (void*)item;
+}
+
+// PlaylistRemoveItem
+void*
+VlcWrapper::PlaylistRemoveItem( int index ) const
+{
+       playlist_item_t* copy = NULL;
+       // check if item exists at the provided index
+       if ( index >= 0 && index < p_playlist->i_size )
+       {
+               playlist_item_t* item = p_playlist->pp_items[index];
+               if ( item )
                {
-                       p_intf->p_sys->b_mute = 0;
+                       // make a copy of the removed item
+                       copy = (playlist_item_t*)PlaylistCloneItem( (void*)item );
+                       // remove item from playlist (unfortunately, this frees it)
+                       playlist_Delete( p_playlist, index );
                }
-        aout_VolumeSet( p_aout, value );
+       }
+       return (void*)copy;
+}
+
+// PlaylistRemoveItem
+void*
+VlcWrapper::PlaylistRemoveItem( void* item ) const
+{
+       playlist_item_t* copy = NULL;
+       for ( int32 i = 0; i < p_playlist->i_size; i++ )
+       {
+               if ( p_playlist->pp_items[i] == item )
+               {
+                       copy = (playlist_item_t*)PlaylistRemoveItem( i );
+                       break;
+               }
+       }
+       return (void*)copy;
+}
+
+// PlaylistAddItem
+bool
+VlcWrapper::PlaylistAddItem( void* item, int index ) const
+{
+       if ( item )
+       {
+               playlist_AddItem( p_playlist, (playlist_item_t*)item,
+                                                 PLAYLIST_INSERT, index );
+       }
+       // TODO: once playlist is returning useful info, return that instead
+       return true;
+}
+
+// PlaylistCloneItem
+void*
+VlcWrapper::PlaylistCloneItem( void* castToItem ) const
+{
+       playlist_item_t* copy = NULL;
+       playlist_item_t* item = (playlist_item_t*)castToItem;
+       if ( item )
+       {
+               copy = (playlist_item_t*)malloc( sizeof( playlist_item_t ) );
+               if ( copy )
+               {
+                       // make a copy of the item at index
+                        *copy = *item;
+                       copy->input.psz_name = strdup( item->input.psz_name );
+                       copy->input.psz_uri  = strdup( item->input.psz_uri );
+               }
+       }
+       return (void*)copy;
+}
+
+// Careful! You need to know what you're doing here!
+// The reason for having it, is to be able to deal with
+// the rather lame list implementation of the playlist.
+// It is meant to help manipulate the playlist with the above
+// methods while keeping it valid.
+//
+// PlaylistSetPlaying
+void
+VlcWrapper::PlaylistSetPlaying( int index ) const
+{
+       if ( index < 0 )
+               index = 0;
+       if ( index >= p_playlist->i_size )
+               index = p_playlist->i_size - 1;
+       p_playlist->i_index = index;
+}
+
+
+/*********
+ * audio *
+ *********/
+
+unsigned short VlcWrapper::GetVolume()
+{
+    unsigned short i_volume;
+    aout_VolumeGet( p_intf, (audio_volume_t*)&i_volume );
+    return i_volume;
+}
+
+void VlcWrapper::SetVolume( int value )
+{
+    if ( p_intf->p_sys->b_mute )
+    {
+        p_intf->p_sys->b_mute = 0;
     }
+    aout_VolumeSet( p_intf, value );
 }
 
 void VlcWrapper::VolumeMute()
 {
-    if( p_aout != NULL )
-       {
-           aout_VolumeGet( p_aout, &p_intf->p_sys->i_saved_volume );
-           aout_VolumeMute( p_aout, NULL );
-           p_intf->p_sys->b_mute = 1;
-       }
+    aout_VolumeMute( p_intf, NULL );
+    p_intf->p_sys->b_mute = 1;
 }
 
 void VlcWrapper::VolumeRestore()
 {
-    if( p_aout != NULL )
-       {
-        aout_VolumeSet( p_aout, p_intf->p_sys->i_saved_volume );
-        p_intf->p_sys->b_mute = 0;
-       }
+    audio_volume_t dummy;
+    aout_VolumeMute( p_intf, &dummy );
+    p_intf->p_sys->b_mute = 0;
 }
 
 bool VlcWrapper::IsMuted()
@@ -637,30 +769,76 @@ bool VlcWrapper::IsMuted()
     return p_intf->p_sys->b_mute;
 }
 
-bool VlcWrapper::HasAudio()
-{
-    return( p_aout != NULL );
-}
-
 /*******
  * DVD *
  *******/
-bool VlcWrapper::HasTitles()
+
+bool VlcWrapper::IsUsingMenus()
 {
     if( !p_input )
+        return false;
+
+    vlc_mutex_lock( &p_playlist->object_lock );
+    if( p_playlist->i_index < 0 )
     {
+        vlc_mutex_unlock( &p_playlist->object_lock );
         return false;
     }
+    
+    char * psz_name = p_playlist->pp_items[p_playlist->i_index]->input.psz_name;
+    if( !strncmp( psz_name, "dvdplay:", 8 ) )
+    {
+        vlc_mutex_unlock( &p_playlist->object_lock );
+        return true;
+    }
+    vlc_mutex_unlock( &p_playlist->object_lock );
+
+    return false;
+}
+
+bool VlcWrapper::HasTitles()
+{
+    if( !p_input )
+        return false;
+
     return ( p_input->stream.i_area_nb > 1 );
 }
 
+BList * VlcWrapper::GetTitles()
+{
+    if( p_input )
+    {
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+      
+        BList *list = new BList( p_input->stream.i_area_nb );
+        BMenuItem *menuItem;
+        BMessage *message;
+        
+        for( unsigned int i = 1; i < p_input->stream.i_area_nb; i++ )
+        {
+            message = new BMessage( TOGGLE_TITLE );
+            message->AddInt32( "index", i );
+            BString helper( "" );
+            helper << i;
+            menuItem = new BMenuItem( helper.String(), message );
+            menuItem->SetMarked( p_input->stream.p_selected_area->i_id == i );
+            list->AddItem( menuItem );
+        }
+        
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+        return list;
+    }
+    return NULL;
+}
+
 void VlcWrapper::PrevTitle()
 {
     int i_id;
     i_id = p_input->stream.p_selected_area->i_id - 1;
     if( i_id > 0 )
     {
-        toggleTitle(i_id);
+        ToggleTitle(i_id);
     }
 }
 
@@ -670,10 +848,41 @@ void VlcWrapper::NextTitle()
     i_id = p_input->stream.p_selected_area->i_id + 1;
     if( i_id < p_input->stream.i_area_nb )
     {
-        toggleTitle(i_id);
+        ToggleTitle(i_id);
+    }
+}
+
+void VlcWrapper::ToggleTitle(int i_title)
+{
+    if( p_input != NULL )
+    {
+        input_ChangeArea( p_input,
+                          p_input->stream.pp_areas[i_title] );
+
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
     }
 }
 
+void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
+{
+       currentIndex = -1;
+       maxIndex = -1;
+       if ( p_input )
+       {
+               vlc_mutex_lock( &p_input->stream.stream_lock );
+
+               maxIndex = p_input->stream.i_area_nb - 1;
+               if ( maxIndex > 0)
+                       currentIndex = p_input->stream.p_selected_area->i_id;
+               else
+                       maxIndex = -1;
+
+               vlc_mutex_unlock( &p_input->stream.stream_lock );
+       }
+}
+
 bool VlcWrapper::HasChapters()
 {
     if( !p_input )
@@ -683,13 +892,42 @@ bool VlcWrapper::HasChapters()
     return ( p_input->stream.p_selected_area->i_part_nb > 1 );
 }
 
+BList * VlcWrapper::GetChapters()
+{
+    if( p_input )
+    {
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+      
+        BList *list = new BList( p_input->stream.p_selected_area->i_part_nb );
+        BMenuItem *menuItem;
+        BMessage *message;
+        
+        for( unsigned int i = 1;
+             i < p_input->stream.p_selected_area->i_part_nb + 1; i++ )
+        {
+            message = new BMessage( TOGGLE_CHAPTER );
+            message->AddInt32( "index", i );
+            BString helper( "" );
+            helper << i;
+            menuItem = new BMenuItem( helper.String(), message );
+            menuItem->SetMarked( p_input->stream.p_selected_area->i_part == i );
+            list->AddItem( menuItem );
+        }
+        
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+        return list;
+    }
+    return NULL;
+}
+
 void VlcWrapper::PrevChapter()
 {
     int i_id;
     i_id = p_input->stream.p_selected_area->i_part - 1;
     if( i_id >= 0 )
     {
-        toggleChapter(i_id);
+        ToggleChapter(i_id);
     }
 }
 
@@ -699,26 +937,21 @@ void VlcWrapper::NextChapter()
     i_id = p_input->stream.p_selected_area->i_part + 1;
     if( i_id >= 0 )
     {
-        toggleChapter(i_id);
+        ToggleChapter(i_id);
     }
 }
 
-void VlcWrapper::TitleInfo( int32 &currentIndex, int32 &maxIndex )
+void VlcWrapper::ToggleChapter(int i_chapter)
 {
-       currentIndex = -1;
-       maxIndex = -1;
-       if ( p_input )
-       {
-               vlc_mutex_lock( &p_input->stream.stream_lock );
-
-               maxIndex = p_input->stream.i_area_nb - 1;
-               if ( maxIndex > 0)
-                       currentIndex = p_input->stream.p_selected_area->i_id;
-               else
-                       maxIndex = -1;
+    if( p_input != NULL )
+    {
+        p_input->stream.p_selected_area->i_part = i_chapter;
+        input_ChangeArea( p_input,
+                          p_input->stream.p_selected_area );
 
-               vlc_mutex_unlock( &p_input->stream.stream_lock );
-       }
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    }
 }
 
 void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
@@ -739,28 +972,41 @@ void VlcWrapper::ChapterInfo( int32 &currentIndex, int32 &maxIndex )
        }
 }
 
-void VlcWrapper::toggleTitle(int i_title)
+/****************
+ * Miscellanous *
+ ****************/
+void VlcWrapper::LoadSubFile( const char * psz_file )
 {
-    if( p_input != NULL )
-    {
-        input_ChangeArea( p_input,
-                          p_input->stream.pp_areas[i_title] );
-
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
-    }
+    config_PutPsz( p_intf, "sub-file", strdup( psz_file ) );
 }
 
-void VlcWrapper::toggleChapter(int i_chapter)
+void VlcWrapper::FilterChange()
 {
-    if( p_input != NULL )
+    if( !p_input )
+        return;
+    
+    vout_thread_t * p_vout;
+    vlc_mutex_lock( &p_input->stream.stream_lock );
+
+    // Warn the vout we are about to change the filter chain
+    p_vout = (vout_thread_t*)vlc_object_find( p_intf, VLC_OBJECT_VOUT,
+                                              FIND_ANYWHERE );
+    if( p_vout )
     {
-        p_input->stream.p_selected_area->i_part = i_chapter;
-        input_ChangeArea( p_input,
-                          p_input->stream.p_selected_area );
+        p_vout->b_filter_change = VLC_TRUE;
+        vlc_object_release( p_vout );
+    }
 
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-        vlc_mutex_unlock( &p_input->stream.stream_lock );
+    // restart all video stream
+    for( unsigned int i = 0; i < p_input->stream.i_es_number; i++ )
+    {
+        if( ( p_input->stream.pp_es[i]->i_cat == VIDEO_ES ) &&
+            ( p_input->stream.pp_es[i]->p_dec != NULL ) )
+        {
+            input_UnselectES( p_input, p_input->stream.pp_es[i] );
+            input_SelectES( p_input, p_input->stream.pp_es[i] );
+        }
     }
+    vlc_mutex_unlock( &p_input->stream.stream_lock );
 }