]> git.sesse.net Git - vlc/commitdiff
Merge branch 1.0-bugfix
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 23 May 2009 09:43:00 +0000 (12:43 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Sat, 23 May 2009 09:43:00 +0000 (12:43 +0300)
1  2 
modules/gui/macosx/controls.h
modules/gui/macosx/controls.m
modules/video_filter/alphamask.c
src/control/media_player.c

index b6c15093600791dbc537f7c9e2bf28e35cc2c424,3708813f47af30ff616afb5dd2cd5281359a7f9e..9b40fdc6ef5e7e1c625c36677a4da49454cacfdb
@@@ -38,8 -38,6 +38,8 @@@
      IBOutlet id o_btn_shuffle;
      IBOutlet id o_btn_addNode;
      IBOutlet id o_btn_repeat;
 +    IBOutlet id o_btn_repeat_embed;
 +    IBOutlet id o_btn_shuffle_embed;
      
      NSImage * o_repeat_single;
      NSImage * o_repeat_all;
      IBOutlet id o_specificTime_mi;
  
      VLCFSPanel *o_fs_panel;
+     BOOL b_lockAspectRatio;
  }
  - (void)controlTintChanged;
  
  - (id)voutView;
+ - (BOOL)aspectRatioIsLocked;
  
  - (IBAction)play:(id)sender;
  - (IBAction)stop:(id)sender;
@@@ -93,6 -93,7 +95,7 @@@
  
  - (IBAction)telxTransparent:(id)sender;
  - (IBAction)telxNavLink:(id)sender;
+ - (IBAction)lockVideosAspectRatio:(id)sender;
  - (IBAction)addSubtitleFile:(id)sender;
  
  - (BOOL)keyEvent:(NSEvent *)o_event;
  
  @end
  
 +/*****************************************************************************
 + * VLCAutoGeneratedMenuContent interface
 + *****************************************************************************
 + * This holds our data for autogenerated menus
 + *****************************************************************************/
 +@interface VLCAutoGeneratedMenuContent : NSObject
 +{
 +    char *psz_name;
 +    vlc_object_t * _vlc_object;
 +    vlc_value_t value;
 +    int i_type;
 +}
 +
 +- (id)initWithVariableName: (const char *)name 
 +                  ofObject: (vlc_object_t *)object
 +                  andValue: (vlc_value_t)value 
 +                    ofType: (int)type;
 +- (const char *)name;
 +- (vlc_value_t)value;
 +- (vlc_object_t *)vlcObject;
 +- (int)type;
 +
 +@end
 +
  /*****************************************************************************
   * VLCTimeField interface
   *****************************************************************************
index aa06beb8e34c36d4a8c0266ea79ec38b5886921e,8b864e6f2bbc62fe03ea5ab437c0fdbc565a4c7b..ef16ff5d6a7b0ad9bd98d528752ebe56286892ee
  #include <vlc_osd.h>
  #include <vlc_keys.h>
  
 -/*****************************************************************************
 - * VLCAutoGeneratedMenuContent interface
 - *****************************************************************************
 - * This holds our data for autogenerated menus
 - *****************************************************************************/
 -@interface VLCAutoGeneratedMenuContent : NSObject
 -{
 -    char *psz_name;
 -    vlc_object_t * _vlc_object;
 -    vlc_value_t value;
 -    int i_type;
 -}
 -
 -- (id)initWithVariableName: (const char *)name 
 -           ofObject: (vlc_object_t *)object
 -           andValue: (vlc_value_t)value 
 -           ofType: (int)type;
 -- (const char *)name;
 -- (vlc_value_t)value;
 -- (vlc_object_t *)vlcObject;
 -- (int)type;
 -
 -@end
 -
  #pragma mark -
  /*****************************************************************************
   * VLCControls implementation
@@@ -50,6 -74,7 +50,7 @@@
  {
      [super init];
      o_fs_panel = [[VLCFSPanel alloc] init];
+     b_lockAspectRatio = YES;
      return self;
  }
  
  
  - (id)voutView
  {
 -    id window;
 -    id voutView = nil;
 -    id embeddedViewList = [[VLCMain sharedInstance] embeddedList];
 -    NSEnumerator *enumerator = [[NSApp orderedWindows] objectEnumerator];
 -    while( !voutView && ( window = [enumerator nextObject] ) )
 +    id o_window;
 +    id o_voutView = nil;
 +    id o_embeddedViewList = [[VLCMain sharedInstance] embeddedList];
 +    NSEnumerator *o_enumerator = [[NSApp orderedWindows] objectEnumerator];
 +    while( !o_voutView && ( o_window = [o_enumerator nextObject] ) )
      {
          /* We have an embedded vout */
 -        if( [embeddedViewList windowContainsEmbedded: window] )
 +        if( [o_embeddedViewList windowContainsEmbedded: o_window] )
          {
 -            voutView = [embeddedViewList viewForWindow: window];
 +            o_voutView = [o_embeddedViewList viewForWindow: o_window];
          }
          /* We have a detached vout */
 -        else if( [[window className] isEqualToString: @"VLCVoutWindow"] )
 +        else if( [[o_window className] isEqualToString: @"VLCVoutWindow"] )
          {
 -            voutView = [window voutView];
 +            o_voutView = [o_window voutView];
          }
      }
 -    return [[voutView retain] autorelease];
 +    return [[o_voutView retain] autorelease];
  }
  
+ - (BOOL)aspectRatioIsLocked
+ {
+     return b_lockAspectRatio;
+ }
  - (IBAction)stop:(id)sender
  {
      intf_thread_t * p_intf = VLCIntf;
  {
      [o_btn_repeat setImage: o_repeat_single];
      [o_btn_repeat setAlternateImage: o_repeat_all];
 +    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeatOneOn"]];
  }
  - (void)repeatAll
  {
      [o_btn_repeat setImage: o_repeat_all];
      [o_btn_repeat setAlternateImage: o_repeat_off];
 +    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeatOn"]];
  }
  - (void)repeatOff
  {
      [o_btn_repeat setImage: o_repeat_off];
      [o_btn_repeat setAlternateImage: o_repeat_single];
 +    [o_btn_repeat_embed setImage: [NSImage imageNamed:@"sidebarRepeat"]];
  }
  - (void)shuffle
  {
      playlist_t *p_playlist = pl_Hold( VLCIntf );
      var_Get( p_playlist, "random", &val );
      [o_btn_shuffle setState: val.b_bool];
 +      if(val.b_bool)
 +        [o_btn_shuffle_embed setImage: [NSImage imageNamed:@"sidebarShuffleOn"]];
 +      else
 +        [o_btn_shuffle_embed setImage: [NSImage imageNamed:@"sidebarShuffle"]];    
      pl_Release( VLCIntf );
  }
  
  
  - (IBAction)showPosition: (id)sender
  {
 -    vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
 -                                             FIND_ANYWHERE );
 -    if( p_vout != NULL )
 +    input_thread_t * p_input = pl_CurrentInput( VLCIntf );
 +    if( p_input != NULL )
      {
 -        intf_thread_t * p_intf = VLCIntf;
 -        var_SetInteger( p_intf->p_libvlc, "key-action", ACTIONID_POSITION );
 -        vlc_object_release( (vlc_object_t *)p_vout );
 +        vout_thread_t *p_vout = input_GetVout( p_input );
 +        if( p_vout != NULL )
 +        {
 +            var_SetInteger( VLCIntf->p_libvlc, "key-action", ACTIONID_POSITION );
 +            vlc_object_release( (vlc_object_t *)p_vout );
 +        }
 +        vlc_object_release( p_input );
      }
  }
  
  - (IBAction)windowAction:(id)sender
  {
      NSString *o_title = [sender title];
 +    input_thread_t * p_input = pl_CurrentInput( VLCIntf );
  
 -    vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
 -                                              FIND_ANYWHERE );
 -    if( p_vout != NULL )
 +    if( p_input != NULL )
      {
 -        id o_vout_view = [self voutView];
 -        if( o_vout_view )
 +        vout_thread_t *p_vout = input_GetVout( p_input );
 +        if( p_vout != NULL )
          {
 -            if( [o_title isEqualToString: _NS("Half Size") ] )
 -                [o_vout_view scaleWindowWithFactor: 0.5 animate: YES];
 -            else if( [o_title isEqualToString: _NS("Normal Size") ] )
 -                [o_vout_view scaleWindowWithFactor: 1.0 animate: YES];
 -            else if( [o_title isEqualToString: _NS("Double Size") ] )
 -                [o_vout_view scaleWindowWithFactor: 2.0 animate: YES];
 -            else if( [o_title isEqualToString: _NS("Float on Top") ] )
 -                [o_vout_view toggleFloatOnTop];
 -            else if( [o_title isEqualToString: _NS("Fit to Screen") ] )
 +            id o_vout_view = [self voutView];
 +            if( o_vout_view )
              {
 -                id o_window = [o_vout_view voutWindow];
 -                if( ![o_window isZoomed] )
 -                    [o_window performZoom:self];
 -            }
 -            else if( [o_title isEqualToString: _NS("Snapshot") ] )
 -            {
 -                [o_vout_view snapshot];
 +                if( [o_title isEqualToString: _NS("Half Size") ] )
 +                    [o_vout_view scaleWindowWithFactor: 0.5 animate: YES];
 +                else if( [o_title isEqualToString: _NS("Normal Size") ] )
 +                    [o_vout_view scaleWindowWithFactor: 1.0 animate: YES];
 +                else if( [o_title isEqualToString: _NS("Double Size") ] )
 +                    [o_vout_view scaleWindowWithFactor: 2.0 animate: YES];
 +                else if( [o_title isEqualToString: _NS("Float on Top") ] )
 +                    [o_vout_view toggleFloatOnTop];
 +                else if( [o_title isEqualToString: _NS("Fit to Screen") ] )
 +                {
 +                    id o_window = [o_vout_view voutWindow];
 +                    if( ![o_window isZoomed] )
 +                        [o_window performZoom:self];
 +                }
 +                else if( [o_title isEqualToString: _NS("Snapshot") ] )
 +                {
 +                    [o_vout_view snapshot];
 +                }
 +                else
 +                {
 +                    /* Fullscreen state for next time will be saved here too */
 +                    [o_vout_view toggleFullscreen];
 +                }
              }
 -            else
 +            vlc_object_release( (vlc_object_t *)p_vout );
 +        }
 +        else
 +        {
 +            playlist_t * p_playlist = pl_Hold( VLCIntf );
 +
 +            if( [o_title isEqualToString: _NS("Fullscreen")] ||
 +                [sender isKindOfClass:[NSButton class]] )
              {
 -                /* Fullscreen state for next time will be saved here too */
 -                [o_vout_view toggleFullscreen];
 +                vlc_value_t val;
 +                var_Get( p_playlist, "fullscreen", &val );
 +                var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
              }
 -        }
 -        vlc_object_release( (vlc_object_t *)p_vout );
 -    }
 -    else
 -    {
 -        playlist_t * p_playlist = pl_Hold( VLCIntf );
  
 -        if( [o_title isEqualToString: _NS("Fullscreen")] ||
 -            [sender isKindOfClass:[NSButton class]] )
 -        {
 -            vlc_value_t val;
 -            var_Get( p_playlist, "fullscreen", &val );
 -            var_Set( p_playlist, "fullscreen", (vlc_value_t)!val.b_bool );
 +            pl_Release( VLCIntf );
          }
 -
 -        pl_Release( VLCIntf );
 +        vlc_object_release( p_input );
      }
 -
  }
  
  - (IBAction)telxTransparent:(id)sender
      }
  }
  
+ - (IBAction)lockVideosAspectRatio:(id)sender
+ {
+     if( [sender state] == NSOffState )
+         [sender setState: NSOnState];
+     else
+         [sender setState: NSOffState];
+     b_lockAspectRatio = !b_lockAspectRatio;
+ }
  - (IBAction)addSubtitleFile:(id)sender
  {
      NSInteger i_returnValue = 0;
              if( input_AddSubtitle( p_input, [[[openPanel filenames] objectAtIndex: i] UTF8String], TRUE ) )
                  msg_Warn( VLCIntf, "unable to load subtitles from '%s'",
                           [[[openPanel filenames] objectAtIndex: i] UTF8String] );
-             i++;
          }
      }
  }
  
      if( key )
      {
 -        vout_thread_t *p_vout = vlc_object_find( VLCIntf, VLC_OBJECT_VOUT,
 -                                              FIND_ANYWHERE );
 -        if( p_vout != NULL )
 +        input_thread_t * p_input = pl_CurrentInput( VLCIntf );
 +        if( p_input != NULL )
          {
 -            /* Escape */
 -            if( key == (unichar) 0x1b )
 +            vout_thread_t *p_vout = input_GetVout( p_input );
 +
 +            if( p_vout != NULL )
              {
 -                id o_vout_view = [self voutView];
 -                if( o_vout_view && [o_vout_view isFullscreen] )
 +                /* Escape */
 +                if( key == (unichar) 0x1b )
                  {
 -                    [o_vout_view toggleFullscreen];
 +                    id o_vout_view = [self voutView];
 +                    if( o_vout_view && [o_vout_view isFullscreen] )
 +                    {
 +                        [o_vout_view toggleFullscreen];
 +                        eventHandled = YES;
 +                    }
 +                }
 +                else if( key == ' ' )
 +                {
 +                    [self play:self];
                      eventHandled = YES;
                  }
 +                vlc_object_release( (vlc_object_t *)p_vout );
              }
 -            else if( key == ' ' )
 -            {
 -                [self play:self];
 -                eventHandled = YES;
 -            }
 -            vlc_object_release( (vlc_object_t *)p_vout );
 +            vlc_object_release( p_input );
          }
      }
      return eventHandled;
      /* make (un)sensitive */
      [o_parent setEnabled: ( val_list.p_list->i_count > 1 )];
  
+     /* Aspect Ratio */
+     if( [[o_parent title] isEqualToString: _NS("Aspect-ratio")] == YES )
+     {
+         NSMenuItem *o_lmi_tmp2;
+         o_lmi_tmp2 = [o_menu addItemWithTitle: _NS("Lock Aspect Ratio") action: @selector(lockVideosAspectRatio:) keyEquivalent: @""];
+         [o_lmi_tmp2 setTarget: self];
+         [o_lmi_tmp2 setEnabled: YES];
+         [o_lmi_tmp2 setState: b_lockAspectRatio];
+         [o_parent setEnabled: YES];
+         [o_menu addItem: [NSMenuItem separatorItem]];
+     }
      /* special case for the subtitles items */
      if( [[o_parent title] isEqualToString: _NS("Subtitles Track")] == YES )
      {
  
      /* clean up everything */
      if( (i_type & VLC_VAR_TYPE) == VLC_VAR_STRING ) free( val.psz_string );
 -    var_Change( p_object, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list );
 +    var_FreeList( &val_list, &text_list );
  }
  
  - (IBAction)toggleVar:(id)sender
      else if( [[o_mi title] isEqualToString: _NS("Previous")] ||
               [[o_mi title] isEqualToString: _NS("Next")] )
      {
 -        /** \todo fix i_size use */
          PL_LOCK;
 -        bEnabled = p_playlist->items.i_size > 1;
 +        bEnabled = playlist_CurrentSize( p_playlist ) > 1;
          PL_UNLOCK;
      }
      else if( [[o_mi title] isEqualToString: _NS("Random")] )
          NSEnumerator *o_enumerator = [o_windows objectEnumerator];
          bEnabled = FALSE;
   
 -        vout_thread_t   *p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
 -                                              FIND_ANYWHERE );
 -        if( p_vout != NULL )
 +        if( p_input != NULL )
          {
 -            if( [[o_mi title] isEqualToString: _NS("Float on Top")] )
 -            {
 -                var_Get( p_vout, "video-on-top", &val );
 -                [o_mi setState: val.b_bool ?  NSOnState : NSOffState];
 -            }
 -
 -            while( (o_window = [o_enumerator nextObject]))
 +            vout_thread_t *p_vout = input_GetVout( p_input );
 +            if( p_vout != NULL )
              {
 -                if( [[o_window className] isEqualToString: @"VLCVoutWindow"] ||
 -                            [[[VLCMain sharedInstance] embeddedList]
 -                            windowContainsEmbedded: o_window])
 +                if( [[o_mi title] isEqualToString: _NS("Float on Top")] )
                  {
 -                    bEnabled = TRUE;
 -                    break;
 +                    var_Get( p_vout, "video-on-top", &val );
 +                    [o_mi setState: val.b_bool ?  NSOnState : NSOffState];
                  }
 +    
 +                while( (o_window = [o_enumerator nextObject]))
 +                {
 +                    if( [[o_window className] isEqualToString: @"VLCVoutWindow"] ||
 +                                [[[VLCMain sharedInstance] embeddedList]
 +                                windowContainsEmbedded: o_window])
 +                    {
 +                        bEnabled = TRUE;
 +                        break;
 +                    }
 +                }
 +    
 +                vlc_object_release( (vlc_object_t *)p_vout );
              }
 -
 -            vlc_object_release( (vlc_object_t *)p_vout );
 +            vlc_object_release( p_input );
          }
          if( [[o_mi title] isEqualToString: _NS("Fullscreen")] )
          {
index b9ddcd9445fe63b5dd012e7bd71485effab168ec,f6b969c075c39d0f3b731a5a1722ac99ea862ae0..a280e14e7682cfd8b83a712e0e34f38cdad38807
@@@ -31,6 -31,7 +31,6 @@@
  
  #include <vlc_common.h>
  #include <vlc_plugin.h>
 -#include <vlc_vout.h>
  
  #include <vlc_image.h>
  #include <vlc_filter.h>
@@@ -89,7 -90,7 +89,7 @@@ static int Create( vlc_object_t *p_thi
      filter_sys_t *p_sys;
      char *psz_string;
  
 -    if( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','A') )
 +    if( p_filter->fmt_in.video.i_chroma != VLC_CODEC_YUVA )
      {
          msg_Err( p_filter,
                   "Unsupported input chroma \"%4s\". "
      config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options,
                         p_filter->p_cfg );
  
-     p_sys->p_mask = NULL;
+     psz_string =
+         var_CreateGetStringCommand( p_filter, CFG_PREFIX "mask" );
      if( psz_string && *psz_string )
      {
          LoadMask( p_filter, psz_string );
              msg_Err( p_filter, "Error while loading mask (%s).",
                       psz_string );
      }
+     else
+        p_sys->p_mask = NULL;
      free( psz_string );
  
      vlc_mutex_init( &p_sys->mask_lock );
-     psz_string =
-         var_CreateGetStringCommand( p_filter, CFG_PREFIX "mask" );
      var_AddCallback( p_filter, CFG_PREFIX "mask", MaskCallback,
                       p_filter );
      p_filter->pf_video_filter = Filter;
@@@ -177,7 -179,7 +178,7 @@@ static void LoadMask( filter_t *p_filte
      video_format_t fmt_in, fmt_out;
      memset( &fmt_in, 0, sizeof( video_format_t ) );
      memset( &fmt_out, 0, sizeof( video_format_t ) );
 -    fmt_out.i_chroma = VLC_FOURCC('Y','U','V','A');
 +    fmt_out.i_chroma = VLC_CODEC_YUVA;
      if( p_filter->p_sys->p_mask )
          picture_Release( p_filter->p_sys->p_mask );
      p_image = image_HandlerCreate( p_filter );
index 1e053e23b4eabf4520c6c2330b82ca8319cb2337,3ac2867b7dbd5c4ba69db3db4c257420ac50d249..82fab1e3579f3a9e92e1445a78b7f962c01d8290
@@@ -78,20 -78,24 +78,20 @@@ static void release_input_thread( libvl
  
      p_input_thread = p_mi->p_input_thread;
  
 -    /* No one is tracking this input_thread apart from us. Destroy it. */
 -    if( p_mi->b_own_its_input_thread )
 -    {
 -        var_DelCallback( p_input_thread, "can-seek",
 -                         input_seekable_changed, p_mi );
 -        var_DelCallback( p_input_thread, "can-pause",
 -                         input_pausable_changed, p_mi );
 -        var_DelCallback( p_input_thread, "intf-event",
 -                         input_event_changed, p_mi );
 -
 -        /* We owned this one */
 -        input_Stop( p_input_thread, b_input_abort );
 -        vlc_thread_join( p_input_thread );
 -
 -        var_Destroy( p_input_thread, "drawable-hwnd" );
 -        var_Destroy( p_input_thread, "drawable-xid" );
 -        var_Destroy( p_input_thread, "drawable-agl" );
 -    }
 +    var_DelCallback( p_input_thread, "can-seek",
 +                     input_seekable_changed, p_mi );
 +    var_DelCallback( p_input_thread, "can-pause",
 +                    input_pausable_changed, p_mi );
 +    var_DelCallback( p_input_thread, "intf-event",
 +                     input_event_changed, p_mi );
 +
 +    /* We owned this one */
 +    input_Stop( p_input_thread, b_input_abort );
 +    vlc_thread_join( p_input_thread );
 +
 +    var_Destroy( p_input_thread, "drawable-hwnd" );
 +    var_Destroy( p_input_thread, "drawable-xid" );
 +    var_Destroy( p_input_thread, "drawable-agl" );
  
      vlc_object_release( p_input_thread );
  
@@@ -215,7 -219,7 +215,7 @@@ input_event_changed( vlc_object_t * p_t
          libvlc_media_set_state( p_mi->p_md, libvlc_state, NULL );
          libvlc_event_send( p_mi->p_event_manager, &event );
      }
 -    else if( newval.i_int == INPUT_EVENT_TIMES )
 +    else if( newval.i_int == INPUT_EVENT_POSITION )
      {
          if( var_GetInteger( p_input, "state" ) != PLAYING_S )
              return VLC_SUCCESS; /* Don't send the position while stopped */
                                                 var_GetTime( p_input, "time" );
          libvlc_event_send( p_mi->p_event_manager, &event );
      }
 +    else if( newval.i_int == INPUT_EVENT_LENGTH )
 +    {
 +        event.type = libvlc_MediaPlayerLengthChanged;
 +        event.u.media_player_length_changed.new_length =
 +                                               var_GetTime( p_input, "length" );
 +        libvlc_event_send( p_mi->p_event_manager, &event );
 +    }
  
      return VLC_SUCCESS;
  
  }
  
 +static void libvlc_media_player_destroy( libvlc_media_player_t * );
 +
  /**************************************************************************
   * Create a Media Instance object.
   *
@@@ -282,9 -277,11 +282,10 @@@ libvlc_media_player_new( libvlc_instanc
      p_mi->drawable.agl = 0;
      p_mi->drawable.xid = 0;
      p_mi->drawable.hwnd = NULL;
+     p_mi->drawable.nsobject = NULL;
      p_mi->p_libvlc_instance = p_libvlc_instance;
      p_mi->p_input_thread = NULL;
      p_mi->i_refcount = 1;
 -    p_mi->b_own_its_input_thread = true;
      vlc_mutex_init( &p_mi->object_lock );
      p_mi->p_event_manager = libvlc_event_manager_new( p_mi,
              p_libvlc_instance, p_e );
              libvlc_MediaPlayerPositionChanged, p_e );
      libvlc_event_manager_register_event_type( p_mi->p_event_manager,
              libvlc_MediaPlayerTimeChanged, p_e );
 +    libvlc_event_manager_register_event_type( p_mi->p_event_manager,
 +            libvlc_MediaPlayerLengthChanged, p_e );
      libvlc_event_manager_register_event_type( p_mi->p_event_manager,
              libvlc_MediaPlayerTitleChanged, p_e );
      libvlc_event_manager_register_event_type( p_mi->p_event_manager,
      /* Snapshot initialization */
      libvlc_event_manager_register_event_type( p_mi->p_event_manager,
             libvlc_MediaPlayerSnapshotTaken, p_e );
 +
      /* Attach a var callback to the global object to provide the glue between
          vout_thread that generates the event and media_player that re-emits it
          with its own event manager
@@@ -354,8 -348,8 +355,8 @@@ libvlc_media_player_new_from_media
                                      libvlc_exception_t *p_e )
  {
      libvlc_media_player_t * p_mi;
 -    p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
  
 +    p_mi = libvlc_media_player_new( p_md->p_libvlc_instance, p_e );
      if( !p_mi )
          return NULL;
  
      return p_mi;
  }
  
 -/**************************************************************************
 - * Create a new media instance object from an input_thread (Libvlc Internal).
 - **************************************************************************/
 -libvlc_media_player_t * libvlc_media_player_new_from_input_thread(
 -                                   struct libvlc_instance_t *p_libvlc_instance,
 -                                   input_thread_t *p_input,
 -                                   libvlc_exception_t *p_e )
 -{
 -    libvlc_media_player_t * p_mi;
 -
 -    if( !p_input )
 -    {
 -        libvlc_exception_raise( p_e, "invalid input thread" );
 -        return NULL;
 -    }
 -
 -    p_mi = libvlc_media_player_new( p_libvlc_instance, p_e );
 -
 -    if( !p_mi )
 -        return NULL;
 -
 -    p_mi->p_md = libvlc_media_new_from_input_item(
 -                    p_libvlc_instance,
 -                    input_GetItem( p_input ), p_e );
 -
 -    if( !p_mi->p_md )
 -    {
 -        libvlc_media_player_destroy( p_mi );
 -        return NULL;
 -    }
 -
 -    /* will be released in media_player_release() */
 -    vlc_object_hold( p_input );
 -
 -    p_mi->p_input_thread = p_input;
 -    p_mi->b_own_its_input_thread = false;
 -
 -    return p_mi;
 -}
 -
  /**************************************************************************
   * Destroy a Media Instance object (libvlc internal)
   *
   * Warning: No lock held here, but hey, this is internal. Caller must lock.
   **************************************************************************/
 -void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
 +static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )
  {
      input_thread_t *p_input_thread;
      libvlc_exception_t p_e;
  
 -    libvlc_exception_init( &p_e );
 -
 -    if( !p_mi )
 -        return;
 +    assert( p_mi );
  
 -      /* Detach Callback from the main libvlc object */
 +    /* Detach Callback from the main libvlc object */
      var_DelCallback( p_mi->p_libvlc_instance->p_libvlc_int,
                       "vout-snapshottaken", SnapshotTakenCallback, p_mi );
  
 +    libvlc_exception_init( &p_e );
      p_input_thread = libvlc_get_input_thread( p_mi, &p_e );
  
      if( libvlc_exception_raised( &p_e ) )
 -    {
 -        libvlc_event_manager_release( p_mi->p_event_manager );
 +        /* no need to worry about no input thread */
          libvlc_exception_clear( &p_e );
 -        free( p_mi );
 -        return; /* no need to worry about no input thread */
 -    }
 -    vlc_mutex_destroy( &p_mi->object_lock );
 -
 -    vlc_object_release( p_input_thread );
 +    else
 +        release_input_thread( p_mi, true );
  
 +    libvlc_event_manager_release( p_mi->p_event_manager );
      libvlc_media_release( p_mi->p_md );
 -
 +    vlc_mutex_destroy( &p_mi->object_lock );
      free( p_mi );
  }
  
   **************************************************************************/
  void libvlc_media_player_release( libvlc_media_player_t *p_mi )
  {
 -    if( !p_mi )
 -        return;
 +    bool destroy;
  
 +    assert( p_mi );
      vlc_mutex_lock( &p_mi->object_lock );
 -
 -    p_mi->i_refcount--;
 -
 -    if( p_mi->i_refcount > 0 )
 -    {
 -        vlc_mutex_unlock( &p_mi->object_lock );
 -        return;
 -    }
 +    destroy = !--p_mi->i_refcount;
      vlc_mutex_unlock( &p_mi->object_lock );
 -    vlc_mutex_destroy( &p_mi->object_lock );
 -
 -    release_input_thread( p_mi, true );
 -
 -    libvlc_event_manager_release( p_mi->p_event_manager );
 -
 -    libvlc_media_release( p_mi->p_md );
  
 -    free( p_mi );
 +    if( destroy )
 +        libvlc_media_player_destroy( p_mi );
  }
  
  /**************************************************************************
@@@ -659,17 -712,31 +660,17 @@@ void libvlc_media_player_stop( libvlc_m
          libvlc_event_send( p_mi->p_event_manager, &event );
      }
  
 -    if( p_mi->b_own_its_input_thread )
 -    {
 -        vlc_mutex_lock( &p_mi->object_lock );
 -        release_input_thread( p_mi, true ); /* This will stop the input thread */
 -        vlc_mutex_unlock( &p_mi->object_lock );
 -    }
 -    else
 -    {
 -        input_thread_t * p_input_thread = libvlc_get_input_thread( p_mi, p_e );
 -
 -        if( !p_input_thread )
 -            return;
 -
 -        input_Stop( p_input_thread, true );
 -        vlc_object_release( p_input_thread );
 -        p_mi->p_input_thread = NULL;
 -    }
 +    vlc_mutex_lock( &p_mi->object_lock );
 +    release_input_thread( p_mi, true ); /* This will stop the input thread */
 +    vlc_mutex_unlock( &p_mi->object_lock );
  }
  
  /**************************************************************************
   * set_nsobject
   **************************************************************************/
  void libvlc_media_player_set_nsobject( libvlc_media_player_t *p_mi,
 -                                                               void * drawable,
 -                                                               libvlc_exception_t *p_e )
 +                                        void * drawable,
 +                                        libvlc_exception_t *p_e )
  {
      (void) p_e;
      p_mi->drawable.nsobject = drawable;
@@@ -1167,8 -1234,6 +1168,8 @@@ libvlc_track_description_t 
                                        libvlc_exception_t *p_e )
  {
      input_thread_t *p_input = libvlc_get_input_thread( p_mi, p_e );
 +    libvlc_track_description_t *p_track_description = NULL,
 +                               *p_actual, *p_previous;
  
      if( !p_input )
          return NULL;
      vlc_value_t val_list, text_list;
      var_Change( p_input, psz_variable, VLC_VAR_GETLIST, &val_list, &text_list);
  
 -    if( val_list.p_list->i_count <= 0 ) /* no tracks */
 -    {
 -        var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
 -        vlc_object_release( p_input );
 -        return NULL;
 -    }
 +    /* no tracks */
 +    if( val_list.p_list->i_count <= 0 )
 +        goto end;
  
 -    libvlc_track_description_t *p_track_description, *p_actual, *p_previous;
      p_track_description = ( libvlc_track_description_t * )
          malloc( sizeof( libvlc_track_description_t ) );
      if ( !p_track_description )
      {
 -        var_Change( p_input, psz_variable, VLC_VAR_FREELIST,
 -                    &val_list, &text_list);
 -        vlc_object_release( p_input );
          libvlc_exception_raise( p_e, "no enough memory" );
 -        return NULL;
 +        goto end;
      }
      p_actual = p_track_description;
      p_previous = NULL;
              if ( !p_actual )
              {
                  libvlc_track_description_release( p_track_description );
 -                var_Change( p_input, psz_variable, VLC_VAR_FREELIST,
 -                            &val_list, &text_list);
 -                vlc_object_release( p_input );
                  libvlc_exception_raise( p_e, "no enough memory" );
 -                return NULL;
 +                goto end;
              }
          }
          p_actual->i_id = val_list.p_list->p_values[i].i_int;
          p_previous = p_actual;
          p_actual =  NULL;
      }
 -    var_Change( p_input, psz_variable, VLC_VAR_FREELIST, &val_list, &text_list);
 +
 +end:
 +    var_FreeList( &val_list, &text_list );
      vlc_object_release( p_input );
  
      return p_track_description;