]> git.sesse.net Git - vlc/commitdiff
* ./modules/gui/macosx/aout.m: M-Audio Revolution fixes.
authorJon Lech Johansen <jlj@videolan.org>
Sun, 23 Feb 2003 05:53:53 +0000 (05:53 +0000)
committerJon Lech Johansen <jlj@videolan.org>
Sun, 23 Feb 2003 05:53:53 +0000 (05:53 +0000)
                                 Dynamic device support.
  * ./modules/gui/macosx: Minor fixes and cosmetic changes.

13 files changed:
extras/MacOSX/Resources/English.lproj/MainMenu.nib/classes.nib
extras/MacOSX/Resources/English.lproj/MainMenu.nib/info.nib
extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib
modules/gui/macosx/aout.m
modules/gui/macosx/info.h
modules/gui/macosx/info.m
modules/gui/macosx/intf.m
modules/gui/macosx/macosx.m
modules/gui/macosx/playlist.h
modules/gui/macosx/playlist.m
modules/gui/macosx/prefs.h
modules/gui/macosx/prefs.m
modules/gui/macosx/vout.m

index 600723e09bc0361c753bb23a2b0deb9a11d41d22..0c4e77c8c6132d50ade4df50b1683890e0c486e5 100644 (file)
@@ -39,7 +39,7 @@
             ACTIONS = {showCategory = id; toggleInfoPanel = id; }; 
             CLASS = VLCInfo; 
             LANGUAGE = ObjC; 
-            OUTLETS = {"o_info_selector" = id; "o_info_view" = id; "o_info_window" = id; }; 
+            OUTLETS = {"o_selector" = id; "o_view" = id; "o_window" = id; }; 
             SUPERCLASS = NSObject; 
         }, 
         {
index 51909c82802f5dccdb4c65105030be41a0360856..b58879804773e40fe97cd77cafb8690602c8222d 100644 (file)
@@ -3,11 +3,11 @@
 <plist version="1.0">
 <dict>
        <key>IBDocumentLocation</key>
-       <string>65 171 365 441 0 0 1280 1002 </string>
+       <string>417 347 365 441 0 0 1600 1178 </string>
        <key>IBEditorPositions</key>
        <dict>
                <key>29</key>
-               <string>16 822 419 44 0 0 1280 1002 </string>
+               <string>22 973 419 44 0 0 1600 1178 </string>
                <key>303</key>
                <string>60 509 104 114 0 0 1280 1002 </string>
                <key>909</key>
@@ -23,8 +23,9 @@
        </array>
        <key>IBOpenObjects</key>
        <array>
-               <integer>29</integer>
+               <integer>1194</integer>
                <integer>21</integer>
+               <integer>29</integer>
        </array>
        <key>IBSystem Version</key>
        <string>6I32</string>
index 16c2490eac5c84c75aa07976a05757c2bd60ec9a..7d7b23b967ed9b31c3a14404852b61598eef3e50 100644 (file)
Binary files a/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib and b/extras/MacOSX/Resources/English.lproj/MainMenu.nib/objects.nib differ
index e3471c40a3622439a92ded60cd54cd68c87f1ca0..052a509eb9caf16fbcc63454fa3d1a16bfa472dc 100644 (file)
@@ -2,7 +2,7 @@
  * aout.m: CoreAudio output plugin
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: aout.m,v 1.23 2003/02/21 16:31:37 hartman Exp $
+ * $Id: aout.m,v 1.24 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Colin Delacroix <colin@zoy.org>
  *          Jon Lech Johansen <jon-vl@nanocrew.net>
@@ -56,7 +56,8 @@ enum AudioDeviceClass
     AudioDeviceClassA52     = 1 << 0,
     AudioDeviceClassPCM2    = 1 << 1,
     AudioDeviceClassPCM4    = 1 << 2,
-    AudioDeviceClassPCM6    = 1 << 3 
+    AudioDeviceClassPCM6    = 1 << 3, 
+    AudioDeviceClassPCM8    = 1 << 4
 };
 
 static struct aout_class_t
@@ -64,20 +65,20 @@ static struct aout_class_t
     UInt32 mFormatID;
     UInt32 mChannelsPerFrame;
     enum AudioDeviceClass class;
-    const char *psz_class;
+    const char * psz_class;
 }
 aout_classes[] =
 {
     { /* old A/52 format type */
         'IAC3', 
-        0
+        2
         AudioDeviceClassA52, 
         "Digital A/52" 
     },
 
     { /* new A/52 format type */
         kAudioFormat60958AC3, 
-        0
+        2
         AudioDeviceClassA52, 
         "Digital A/52"
     },
@@ -101,6 +102,13 @@ aout_classes[] =
         6, 
         AudioDeviceClassPCM6, 
         "6 Channel PCM"
+    },
+
+    {
+        kAudioFormatLinearPCM,
+        8,
+        AudioDeviceClassPCM8,
+        "8 Channel PCM"
     }
 }; 
 
@@ -123,8 +131,9 @@ struct aout_option_t
 struct aout_dev_t
 {
     AudioDeviceID devid;
-    char *psz_device_name;
+    char * psz_device_name;
     UInt32 i_streams;
+    UInt32 * pi_streams;
     AudioStreamBasicDescription ** pp_streams;
 };
 
@@ -136,13 +145,18 @@ struct aout_dev_t
  *****************************************************************************/
 struct aout_sys_t
 {
+    vlc_mutex_t                 lock;
+    vlc_bool_t                  b_hwinfo;
+    UInt32                      i_def_dev;
     UInt32                      i_devices;
     struct aout_dev_t *         p_devices;
+    UInt32                      i_sel_opt;
     UInt32                      i_options;
-    struct aout_option_t *      p_options;   
+    struct aout_option_t *      p_options;
 
     AudioDeviceID               devid;
     AudioStreamBasicDescription stream_format;
+    UInt32                      b_dev_alive;
 
     UInt32                      i_buffer_size;
     mtime_t                     clock_diff;
@@ -151,28 +165,44 @@ struct aout_sys_t
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int      InitHardware    ( aout_instance_t *p_aout );
-static int      InitDevice      ( UInt32 i_dev, aout_instance_t *p_aout ); 
-static void     FreeDevice      ( UInt32 i_dev, aout_instance_t *p_aout ); 
-static void     FreeHardware    ( aout_instance_t *p_aout );
-static int      GetDevice       ( aout_instance_t *p_aout, 
-                                  AudioDeviceID *p_devid );
-static int      GetStreamID     ( AudioDeviceID devid, UInt32 i_idx,
-                                  AudioStreamID * p_sid );
-static int      InitStream      ( UInt32 i_dev, aout_instance_t *p_aout,
-                                  UInt32 i_idx );
-static void     FreeStream      ( UInt32 i_dev, aout_instance_t *p_aout,
-                                  UInt32 i_idx );
-
-static void     Play            ( aout_instance_t *p_aout );
-
-static OSStatus IOCallback      ( AudioDeviceID inDevice,
-                                  const AudioTimeStamp *inNow, 
-                                  const void *inInputData, 
-                                  const AudioTimeStamp *inInputTime,
-                                  AudioBufferList *outOutputData, 
-                                  const AudioTimeStamp *inOutputTime, 
-                                  void *threadGlobals );
+static int      InitHardwareInfo ( aout_instance_t * p_aout );
+static int      InitDeviceInfo   ( UInt32 i_dev, aout_instance_t * p_aout ); 
+static void     FreeDeviceInfo   ( UInt32 i_dev, aout_instance_t * p_aout ); 
+static void     FreeHardwareInfo ( aout_instance_t * p_aout );
+static int      InitDevice       ( aout_instance_t * p_aout );
+static void     FreeDevice       ( aout_instance_t * p_aout );
+static int      GetStreamID      ( AudioDeviceID devid, UInt32 i_idx,
+                                   AudioStreamID * p_sid );
+static int      InitStreamInfo   ( UInt32 i_dev, aout_instance_t * p_aout,
+                                   UInt32 i_idx );
+static void     FreeStreamInfo   ( UInt32 i_dev, aout_instance_t * p_aout,
+                                   UInt32 i_idx );
+static void     InitDeviceVar    ( aout_instance_t * p_aout, int i_option,
+                                   vlc_bool_t b_change );
+
+static void     Play             ( aout_instance_t * p_aout );
+
+static OSStatus IOCallback       ( AudioDeviceID inDevice,
+                                   const AudioTimeStamp * inNow, 
+                                   const void * inInputData, 
+                                   const AudioTimeStamp * inInputTime,
+                                   AudioBufferList * outOutputData, 
+                                   const AudioTimeStamp * inOutputTime, 
+                                   void * threadGlobals );
+
+static OSStatus HardwareListener ( AudioHardwarePropertyID inPropertyID,
+                                   void * inClientData );
+
+static OSStatus DeviceListener   ( AudioDeviceID inDevice,
+                                   UInt32 inChannel,
+                                   Boolean isInput,
+                                   AudioDevicePropertyID inPropertyID,
+                                   void * inClientData );
+
+static OSStatus StreamListener   ( AudioStreamID inStream,
+                                   UInt32 inChannel,
+                                   AudioDevicePropertyID inPropertyID,
+                                   void * inClientData );
 
 /*****************************************************************************
  * Open: open a CoreAudio HAL device
@@ -180,8 +210,7 @@ static OSStatus IOCallback      ( AudioDeviceID inDevice,
 int E_(OpenAudio)( vlc_object_t * p_this )
 {
     OSStatus err;
-    vlc_value_t val;
-    UInt32 i, i_param_size;
+    UInt32 i_param_size;
     struct aout_sys_t * p_sys;
     aout_instance_t * p_aout = (aout_instance_t *)p_this;
 
@@ -194,62 +223,47 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     }
 
     memset( p_sys, 0, sizeof( struct aout_sys_t ) );
+
     p_aout->output.p_sys = p_sys;
+    p_aout->output.pf_play = Play;
 
-    if( InitHardware( p_aout ) )
+    vlc_mutex_init( p_aout, &p_sys->lock );
+
+    if( InitHardwareInfo( p_aout ) )
     {
-        msg_Err( p_aout, "InitHardware failed" );
+        msg_Err( p_aout, "InitHardwareInfo failed" );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     } 
 
     if( var_Type( p_aout, "audio-device" ) == 0 )
     {
-        UInt32 i_option = config_GetInt( p_aout, "macosx-adev" );
-
-        var_Create( p_aout, "audio-device", VLC_VAR_STRING | 
-                                            VLC_VAR_HASCHOICE );
-
-        for( i = 0; i < p_sys->i_options; i++ )
-        {
-            val.psz_string = p_sys->p_options[i].sz_option;
-            var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
-
-            if( i == i_option )
-            {
-                var_Set( p_aout, "audio-device", val );
-            }
-        }
-
-        var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart,
-                         NULL );
-
-        val.b_bool = VLC_TRUE;
-        var_Set( p_aout, "intf-change", val );
+        InitDeviceVar( p_aout, config_GetInt( p_aout, "macosx-adev" ),
+                       VLC_FALSE );
     }
 
-    /* Get requested device */
-    if( GetDevice( p_aout, &p_sys->devid ) )
+    if( InitDevice( p_aout ) )
     {
-        msg_Err( p_aout, "GetDevice failed" );
-        FreeHardware( p_aout );
+        msg_Err( p_aout, "InitDevice failed" );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     } 
 
-    p_aout->output.pf_play = Play;
-    aout_VolumeSoftInit( p_aout );
-
     /* Get a description of the stream format */
     i_param_size = sizeof( AudioStreamBasicDescription ); 
-    err = AudioDeviceGetProperty( p_sys->devid, 0, false
+    err = AudioDeviceGetProperty( p_sys->devid, 0, FALSE
                                   kAudioDevicePropertyStreamFormat,
                                   &i_param_size, &p_sys->stream_format );
     if( err != noErr )
     {
         msg_Err( p_aout, "failed to get stream format: [%4.4s]", 
                  (char *)&err );
-        FreeHardware( p_aout );
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     }
@@ -263,14 +277,16 @@ int E_(OpenAudio)( vlc_object_t * p_this )
 
     /* Get the buffer size */
     i_param_size = sizeof( p_sys->i_buffer_size );
-    err = AudioDeviceGetProperty( p_sys->devid, 0, false
+    err = AudioDeviceGetProperty( p_sys->devid, 0, FALSE
                                   kAudioDevicePropertyBufferSize, 
                                   &i_param_size, &p_sys->i_buffer_size );
     if( err != noErr )
     {
         msg_Err( p_aout, "failed to get buffer size: [%4.4s]", 
                  (char *)&err );
-        FreeHardware( p_aout );
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     }
@@ -284,14 +300,16 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     {
         p_sys->i_buffer_size = AOUT_SPDIF_SIZE;
         i_param_size = sizeof( p_sys->i_buffer_size );
-        err = AudioDeviceSetProperty( p_sys->devid, 0, 0, false,
+        err = AudioDeviceSetProperty( p_sys->devid, 0, 0, FALSE,
                                       kAudioDevicePropertyBufferSize,
                                       i_param_size, &p_sys->i_buffer_size );
         if( err != noErr )
         {
             msg_Err( p_aout, "failed to set buffer size: [%4.4s]", 
                      (char *)&err );
-            FreeHardware( p_aout );
+            FreeDevice( p_aout );
+            FreeHardwareInfo( p_aout );
+            vlc_mutex_destroy( &p_sys->lock );
             free( (void *)p_sys );
             return( VLC_EGENERIC );
         }
@@ -305,27 +323,48 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     case kAudioFormatLinearPCM:
         p_aout->output.output.i_format = VLC_FOURCC('f','l','3','2');
 
-        if( p_sys->stream_format.mChannelsPerFrame == 6 )
+        switch( p_sys->stream_format.mChannelsPerFrame )
         {
+        case 2:
             p_aout->output.output.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
-                AOUT_CHAN_CENTER | AOUT_CHAN_REARRIGHT |
-                AOUT_CHAN_REARLEFT | AOUT_CHAN_LFE;
-        }
-        else if( p_sys->stream_format.mChannelsPerFrame == 4 )
-        {
+                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+            break;
+
+        case 4:
             p_aout->output.output.i_physical_channels =
                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                 AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
-        }
-        else
-        {
+            break;
+
+        case 6:
             p_aout->output.output.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
+                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
+                AOUT_CHAN_CENTER | AOUT_CHAN_LFE;
+            break;
+
+        case 8:
+            p_aout->output.output.i_physical_channels =
+                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
+                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
+                AOUT_CHAN_CENTER | AOUT_CHAN_LFE |
+                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
+            break;
+
+        default:
+            msg_Err( p_aout, "unknown channel count: [%ld]",
+                     p_sys->stream_format.mChannelsPerFrame ); 
+            FreeDevice( p_aout );
+            FreeHardwareInfo( p_aout );
+            vlc_mutex_destroy( &p_sys->lock );
+            free( (void *)p_sys );
+            return( VLC_EGENERIC );
         }
 
         p_aout->output.i_nb_samples = (int)( p_sys->i_buffer_size /
                                       p_sys->stream_format.mBytesPerFrame );
+
+        aout_VolumeSoftInit( p_aout );
         break;
 
     case 'IAC3':
@@ -334,19 +373,23 @@ int E_(OpenAudio)( vlc_object_t * p_this )
         p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE;
         p_aout->output.output.i_frame_length = A52_FRAME_NB;
         p_aout->output.i_nb_samples = p_aout->output.output.i_frame_length;
+
+        aout_VolumeNoneInit( p_aout );
         break;
 
     default:
         msg_Err( p_aout, "unknown hardware format: [%4.4s]", 
                  (char *)&p_sys->stream_format.mFormatID );
-        FreeHardware( p_aout );
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     }
 
     /* Set buffer frame size */
     i_param_size = sizeof( p_aout->output.i_nb_samples );
-    err = AudioDeviceSetProperty( p_sys->devid, 0, 0, false,
+    err = AudioDeviceSetProperty( p_sys->devid, 0, 0, FALSE,
                                   kAudioDevicePropertyBufferFrameSize,
                                   i_param_size,
                                   &p_aout->output.i_nb_samples );
@@ -354,7 +397,9 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     {
         msg_Err( p_aout, "failed to set buffer frame size: [%4.4s]", 
                  (char *)&err );
-        FreeHardware( p_aout );
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     }
@@ -370,7 +415,9 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     {
         msg_Err( p_aout, "AudioDeviceAddIOProc failed: [%4.4s]",
                  (char *)&err );
-        FreeHardware( p_aout );
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
         return( VLC_EGENERIC );
     }
@@ -381,8 +428,54 @@ int E_(OpenAudio)( vlc_object_t * p_this )
     {
         msg_Err( p_aout, "AudioDeviceStart failed: [%4.4s]",
                  (char *)&err );
-        FreeHardware( p_aout );
+
+        err = AudioDeviceRemoveIOProc( p_sys->devid, 
+                                       (AudioDeviceIOProc)IOCallback );
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]",
+                     (char *)&err );
+        }
+
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
+        free( (void *)p_sys );
+
+        return( VLC_EGENERIC );
+    }
+
+    err = AudioHardwareAddPropertyListener( kAudioHardwarePropertyDevices,
+                                            HardwareListener, 
+                                            (void *)p_aout ); 
+    if( err != noErr )
+    {
+        msg_Err( p_aout, "AudioHardwareAddPropertyListener failed: %4.4s",
+                 (char *)&err );
+
+        /* Stop device */
+        err = AudioDeviceStop( p_sys->devid, 
+                               (AudioDeviceIOProc)IOCallback ); 
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioDeviceStop failed: [%4.4s]",
+                     (char *)&err );
+        }
+
+        /* Remove callback */
+        err = AudioDeviceRemoveIOProc( p_sys->devid,
+                                       (AudioDeviceIOProc)IOCallback );
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]",
+                     (char *)&err );
+        }
+
+        FreeDevice( p_aout );
+        FreeHardwareInfo( p_aout );
+        vlc_mutex_destroy( &p_sys->lock );
         free( (void *)p_sys );
+
         return( VLC_EGENERIC );
     }
 
@@ -402,23 +495,40 @@ void E_(CloseAudio)( aout_instance_t * p_aout )
     OSStatus err; 
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
 
-    /* Stop device */
-    err = AudioDeviceStop( p_sys->devid, (AudioDeviceIOProc)IOCallback ); 
-    if( err != noErr )
+    if( p_sys->b_dev_alive )
     {
-        msg_Err( p_aout, "AudioDeviceStop failed: [%4.4s]", (char *)&err );
+        /* Stop device */
+        err = AudioDeviceStop( p_sys->devid, 
+                               (AudioDeviceIOProc)IOCallback ); 
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioDeviceStop failed: [%4.4s]",
+                     (char *)&err );
+        }
+
+        /* Remove callback */
+        err = AudioDeviceRemoveIOProc( p_sys->devid,
+                                       (AudioDeviceIOProc)IOCallback );
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]",
+                     (char *)&err );
+        }
+
+        FreeDevice( p_aout );
     }
 
-    /* Remove callback */
-    err = AudioDeviceRemoveIOProc( p_sys->devid,
-                                   (AudioDeviceIOProc)IOCallback );
+    err = AudioHardwareRemovePropertyListener( kAudioHardwarePropertyDevices,
+                                               HardwareListener );
     if( err != noErr )
     {
-        msg_Err( p_aout, "AudioDeviceRemoveIOProc failed: [%4.4s]",
+        msg_Err( p_aout, "AudioHardwareRemovePropertyListener failed: [%4.4s]",
                  (char *)&err );
     }
 
-    FreeHardware( p_aout );
+    FreeHardwareInfo( p_aout );
+
+    vlc_mutex_destroy( &p_sys->lock );
 
     free( p_sys );
 }
@@ -434,12 +544,12 @@ static void Play( aout_instance_t * p_aout )
  * IOCallback: callback for audio output
  *****************************************************************************/
 static OSStatus IOCallback( AudioDeviceID inDevice,
-                            const AudioTimeStamp *inNow, 
-                            const void *inInputData,
-                            const AudioTimeStamp *inInputTime, 
-                            AudioBufferList *outOutputData,
-                            const AudioTimeStamp *inOutputTime, 
-                            void *threadGlobals )
+                            const AudioTimeStamp * inNow, 
+                            const void * inInputData,
+                            const AudioTimeStamp * inInputTime, 
+                            AudioBufferList * outOutputData,
+                            const AudioTimeStamp * inOutputTime, 
+                            void * threadGlobals )
 {
     aout_buffer_t * p_buffer;
     AudioTimeStamp  host_time;
@@ -470,17 +580,18 @@ static OSStatus IOCallback( AudioDeviceID inDevice,
     {
         if( p_aout->output.output.i_format == VLC_FOURCC('f','l','3','2') )
         {
-            int i;
-            int i_size = p_sys->i_buffer_size / sizeof(float);
-            
-            float * a = (float *)outOutputData->mBuffers[ 0 ].mData;
-            for ( i = 0 ; i < i_size ; i++ )
-                *a++ = 0.0;
+            UInt32 i, i_size = p_sys->i_buffer_size / sizeof(float);
+            float * p = (float *)outOutputData->mBuffers[ 0 ].mData;
+
+            for( i = 0; i < i_size; i++ )
+            {
+                *p++ = 0.0;
+            }
         }
         else
         {
             memset( outOutputData->mBuffers[ 0 ].mData, 
-                0, p_sys->i_buffer_size );
+                    0, p_sys->i_buffer_size );
         }
     }
 
@@ -488,16 +599,19 @@ static OSStatus IOCallback( AudioDeviceID inDevice,
 }
 
 /*****************************************************************************
- * InitHardware 
+ * InitHardwareInfo
  *****************************************************************************/
-static int InitHardware( aout_instance_t * p_aout )
+static int InitHardwareInfo( aout_instance_t * p_aout )
 {
     OSStatus err;
     UInt32 i, i_param_size;
+    AudioDeviceID devid_def; 
     AudioDeviceID * p_devices;
 
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
 
+    vlc_mutex_lock( &p_sys->lock );
+
     /* Get number of devices */
     err = AudioHardwareGetPropertyInfo( kAudioHardwarePropertyDevices,
                                         &i_param_size, NULL );
@@ -505,6 +619,7 @@ static int InitHardware( aout_instance_t * p_aout )
     {
         msg_Err( p_aout, "AudioHardwareGetPropertyInfo failed: [%4.4s]",
                  (char *)&err );
+        vlc_mutex_unlock( &p_sys->lock );
         return( VLC_EGENERIC );
     }
 
@@ -513,6 +628,7 @@ static int InitHardware( aout_instance_t * p_aout )
     if( p_sys->i_devices < 1 )
     {
         msg_Err( p_aout, "no devices found" );
+        vlc_mutex_unlock( &p_sys->lock );
         return( VLC_EGENERIC );
     }
 
@@ -523,6 +639,7 @@ static int InitHardware( aout_instance_t * p_aout )
     if( p_devices == NULL )
     {
         msg_Err( p_aout, "out of memory" );
+        vlc_mutex_unlock( &p_sys->lock );
         return( VLC_ENOMEM );
     }
 
@@ -534,6 +651,19 @@ static int InitHardware( aout_instance_t * p_aout )
         msg_Err( p_aout, "AudioHardwareGetProperty failed: [%4.4s]",
                  (char *)&err );
         free( (void *)p_devices );
+        vlc_mutex_unlock( &p_sys->lock );
+        return( VLC_EGENERIC );
+    }
+
+    i_param_size = sizeof( AudioDeviceID );
+    err = AudioHardwareGetProperty( kAudioHardwarePropertyDefaultOutputDevice,
+                                    &i_param_size, (void *)&devid_def );
+    if( err != noErr )
+    {
+        msg_Err( p_aout, "AudioHardwareGetProperty failed: [%4.4s]",
+                 (char *)&err );
+        free( (void *)p_devices );
+        vlc_mutex_unlock( &p_sys->lock );
         return( VLC_EGENERIC );
     }
 
@@ -543,44 +673,59 @@ static int InitHardware( aout_instance_t * p_aout )
     {
         msg_Err( p_aout, "out of memory" );
         free( (void *)p_devices );
+        vlc_mutex_unlock( &p_sys->lock );
         return( VLC_ENOMEM );
     }    
 
+    p_sys->i_options = 0;
+    p_sys->p_options = NULL;
+
     for( i = 0; i < p_sys->i_devices; i++ )
     {
         p_sys->p_devices[i].devid = p_devices[i];
 
-        if( InitDevice( i, p_aout ) )
+        if( p_devices[i] == devid_def )
+        {
+            p_sys->i_def_dev = i;
+        }
+
+        if( InitDeviceInfo( i, p_aout ) )
         {
             UInt32 j;
 
-            msg_Err( p_aout, "InitDevice(%ld) failed", i );
+            msg_Err( p_aout, "InitDeviceInfo(%ld) failed", i );
 
             for( j = 0; j < i; j++ )
             {
-                FreeDevice( j, p_aout );
+                FreeDeviceInfo( j, p_aout );
             }
     
             free( (void *)p_sys->p_devices );
             free( (void *)p_devices );
 
+            vlc_mutex_unlock( &p_sys->lock );
+
             return( VLC_EGENERIC );
         }
     }
 
     free( (void *)p_devices );
 
+    p_sys->b_hwinfo = VLC_TRUE;
+
+    vlc_mutex_unlock( &p_sys->lock );
+
     return( VLC_SUCCESS );
 }
 
 /*****************************************************************************
- * InitDevice
+ * InitDeviceInfo
  *****************************************************************************/
-static int InitDevice( UInt32 i_dev, aout_instance_t * p_aout ) 
+static int InitDeviceInfo( UInt32 i_dev, aout_instance_t * p_aout ) 
 {
     OSStatus err;
     UInt32 i, i_param_size;
-    AudioBufferList *p_buffer_list;
+    AudioBufferList * p_buffer_list;
 
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
     struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
@@ -656,6 +801,15 @@ static int InitDevice( UInt32 i_dev, aout_instance_t * p_aout )
     msg_Dbg( p_aout, "device [%ld] has [%ld] streams", 
              i_dev, p_dev->i_streams ); 
 
+    p_dev->pi_streams = (UInt32 *)malloc( p_dev->i_streams *
+                                          sizeof( *p_dev->pi_streams ) );
+    if( p_dev->pi_streams == NULL )
+    {
+        msg_Err( p_aout, "out of memory" );
+        free( (void *)p_dev->psz_device_name );
+        return( VLC_ENOMEM );
+    }
+
     p_dev->pp_streams = (AudioStreamBasicDescription **) 
                         malloc( p_dev->i_streams * 
                                 sizeof( *p_dev->pp_streams ) );
@@ -663,23 +817,25 @@ static int InitDevice( UInt32 i_dev, aout_instance_t * p_aout )
     {
         msg_Err( p_aout, "out of memory" );
         free( (void *)p_dev->psz_device_name );
+        free( (void *)p_dev->pi_streams );
         return( VLC_ENOMEM );
     } 
 
     for( i = 0; i < p_dev->i_streams; i++ )
     {
-        if( InitStream( i_dev, p_aout, i ) )
+        if( InitStreamInfo( i_dev, p_aout, i ) )
         {
             UInt32 j;
 
-            msg_Err( p_aout, "InitStream(%ld, %ld) failed", i_dev, i );
+            msg_Err( p_aout, "InitStreamInfo(%ld, %ld) failed", i_dev, i );
 
             for( j = 0; j < i; j++ )
             {
-                FreeStream( i_dev, p_aout, j );
+                FreeStreamInfo( i_dev, p_aout, j );
             }
 
             free( (void *)p_dev->psz_device_name );
+            free( (void *)p_dev->pi_streams );
             free( (void *)p_dev->pp_streams );
 
             return( VLC_EGENERIC );
@@ -690,9 +846,9 @@ static int InitDevice( UInt32 i_dev, aout_instance_t * p_aout )
 }
 
 /*****************************************************************************
- * FreeDevice 
+ * FreeDeviceInfo
  *****************************************************************************/
-static void FreeDevice( UInt32 i_dev, aout_instance_t * p_aout )
+static void FreeDeviceInfo( UInt32 i_dev, aout_instance_t * p_aout )
 {
     UInt32 i;
 
@@ -701,29 +857,42 @@ static void FreeDevice( UInt32 i_dev, aout_instance_t * p_aout )
 
     for( i = 0; i < p_dev->i_streams; i++ )
     {
-        FreeStream( i_dev, p_aout, i );
+        FreeStreamInfo( i_dev, p_aout, i );
     }
 
     free( (void *)p_dev->pp_streams );
+    free( (void *)p_dev->pi_streams );
     free( (void *)p_dev->psz_device_name );
 }
 
 /*****************************************************************************
- * FreeHardware 
+ * FreeHardwareInfo
  *****************************************************************************/
-static void FreeHardware( aout_instance_t * p_aout )
+static void FreeHardwareInfo( aout_instance_t * p_aout )
 {
     UInt32 i;
 
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
 
+    vlc_mutex_lock( &p_sys->lock );
+
+    if( !p_sys->b_hwinfo )
+    {
+        vlc_mutex_unlock( &p_sys->lock );
+        return;
+    }
+
     for( i = 0; i < p_sys->i_devices; i++ )
     {
-        FreeDevice( i, p_aout );
+        FreeDeviceInfo( i, p_aout );
     }
 
     free( (void *)p_sys->p_options );
     free( (void *)p_sys->p_devices );
+
+    p_sys->b_hwinfo = VLC_FALSE;
+
+    vlc_mutex_unlock( &p_sys->lock );
 }
 
 /*****************************************************************************
@@ -767,15 +936,14 @@ static int GetStreamID( AudioDeviceID devid, UInt32 i_idx,
 }
 
 /*****************************************************************************
- * InitStream
+ * InitStreamInfo
  *****************************************************************************/
-static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
-                       UInt32 i_idx )
+static int InitStreamInfo( UInt32 i_dev, aout_instance_t * p_aout,
+                           UInt32 i_idx )
 {
     OSStatus err;
     AudioStreamID i_sid;
-    UInt32 i, i_streams;
-    UInt32 j, i_param_size;
+    UInt32 i, j, i_param_size;
 
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
     struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
@@ -796,9 +964,10 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
         return( VLC_EGENERIC );
     }
 
-    i_streams = i_param_size / sizeof( AudioStreamBasicDescription );
-
 #define P_STREAMS p_dev->pp_streams[i_idx]
+#define I_STREAMS p_dev->pi_streams[i_idx]
+
+    I_STREAMS = i_param_size / sizeof( AudioStreamBasicDescription );
 
     P_STREAMS = (AudioStreamBasicDescription *)malloc( i_param_size );
     if( P_STREAMS == NULL )
@@ -807,6 +976,8 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
         return( VLC_ENOMEM );
     }
 
+    memset( P_STREAMS, 0, i_param_size );
+
     err = AudioStreamGetProperty( i_sid, 0,
                                   kAudioStreamPropertyPhysicalFormats,
                                   &i_param_size, P_STREAMS );
@@ -821,10 +992,8 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
     for( j = 0; j < N_AOUT_CLASSES; j++ )
     {
         vlc_bool_t b_found = 0;
-        UInt32 i_channels = 0xFFFFFFFF;
-        UInt32 i_sdx = 0;
 
-        for( i = 0; i < i_streams; i++ )
+        for( i = 0; i < I_STREAMS; i++ )
         {
             if( j == 0 )
             {
@@ -832,19 +1001,22 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
                                                     P_STREAMS[i] ) );
             }
 
-            if( ( P_STREAMS[i].mFormatID != aout_classes[j].mFormatID ) ||
-                ( P_STREAMS[i].mChannelsPerFrame < 
-                  aout_classes[j].mChannelsPerFrame ) )
+            if( ( P_STREAMS[i].mFormatID == 'IAC3' ||
+                  P_STREAMS[i].mFormatID == kAudioFormat60958AC3 ) &&
+                !AOUT_FMT_NON_LINEAR( &p_aout->output.output ) ) 
             {
                 continue;
             }
 
-            if( P_STREAMS[i].mChannelsPerFrame < i_channels )
+            if( ( P_STREAMS[i].mFormatID != aout_classes[j].mFormatID ) ||
+                ( P_STREAMS[i].mChannelsPerFrame != 
+                  aout_classes[j].mChannelsPerFrame ) )
             {
-                i_channels = P_STREAMS[i].mChannelsPerFrame;
-                i_sdx = i;
-                b_found = 1;
+                continue;
             }
+
+            b_found = 1;
+            break;
         }
 
         if( b_found )
@@ -873,7 +1045,7 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
             AOUT_OPTION.i_sid = i_sid;
             AOUT_OPTION.i_dev = i_dev; 
             AOUT_OPTION.i_idx = i_idx;
-            AOUT_OPTION.i_sdx = i_sdx;
+            AOUT_OPTION.i_sdx = i;
             AOUT_OPTION.i_cdx = j;
 
 #undef AOUT_OPTION
@@ -882,16 +1054,17 @@ static int InitStream( UInt32 i_dev, aout_instance_t *p_aout,
         } 
     }
 
+#undef I_STREAMS
 #undef P_STREAMS
 
     return( VLC_SUCCESS );
 }
 
 /*****************************************************************************
- * FreeStream 
+ * FreeStreamInfo
  *****************************************************************************/
-static void FreeStream( UInt32 i_dev, aout_instance_t *p_aout,
-                        UInt32 i_idx )
+static void FreeStreamInfo( UInt32 i_dev, aout_instance_t * p_aout,
+                            UInt32 i_idx )
 {
     struct aout_sys_t * p_sys = p_aout->output.p_sys;
     struct aout_dev_t * p_dev = &p_sys->p_devices[i_dev];
@@ -900,13 +1073,16 @@ static void FreeStream( UInt32 i_dev, aout_instance_t *p_aout,
 }
 
 /*****************************************************************************
- * GetDevice 
+ * InitDevice 
  *****************************************************************************/
-static int GetDevice( aout_instance_t *p_aout, AudioDeviceID *p_devid ) 
+static int InitDevice( aout_instance_t * p_aout ) 
 {
     OSStatus err;
     vlc_value_t val;
     unsigned int i_option;
+    vlc_bool_t b_found = VLC_FALSE;
+    UInt32 i, i_stream, i_param_size;
+    AudioStreamBasicDescription desc;
 
     struct aout_dev_t * p_dev;
     struct aout_option_t * p_option;
@@ -929,26 +1105,319 @@ static int GetDevice( aout_instance_t *p_aout, AudioDeviceID *p_devid )
     p_option = &p_sys->p_options[i_option];
     p_dev = &p_sys->p_devices[p_option->i_dev];
 
+    msg_Dbg( p_aout, "getting device [%ld]", p_option->i_dev );
+
+    i_param_size = sizeof( p_sys->b_dev_alive );
+    err = AudioDeviceGetProperty( p_dev->devid, 0, FALSE,
+                                  kAudioDevicePropertyDeviceIsAlive,
+                                  &i_param_size, &p_sys->b_dev_alive );
+    if( err != noErr )
+    {
+        msg_Err( p_aout, "AudioDeviceGetProperty failed: %4.4s",
+                 (char *)&err );
+        return( VLC_EGENERIC );
+    }
+
 #define P_STREAMS p_dev->pp_streams[p_option->i_idx]
+#define I_STREAMS p_dev->pi_streams[p_option->i_idx]
 
-    err = AudioStreamSetProperty( p_option->i_sid, 0, 0,
+    for( i = 0; i < I_STREAMS; i++ )
+    {
+        if( P_STREAMS[i].mFormatID == 
+            aout_classes[p_option->i_cdx].mFormatID &&
+            P_STREAMS[i].mSampleRate == p_aout->output.output.i_rate )  
+        {
+            b_found = VLC_TRUE;
+            break;
+        }
+    } 
+
+    i_stream = b_found ? i : p_option->i_sdx;
+
+    i_param_size = sizeof( desc );
+    memset( &desc, 0, i_param_size );
+    err = AudioStreamGetProperty( p_option->i_sid, 0,
                                   kAudioStreamPropertyPhysicalFormat,
-                                  sizeof( P_STREAMS[p_option->i_sdx] ),
-                                  &P_STREAMS[p_option->i_sdx] ); 
+                                  &i_param_size, (void *)&desc );
     if( err != noErr )
     {
-        msg_Err( p_aout, "AudioStreamSetProperty failed: [%4.4s]",
+        msg_Err( p_aout, "AudioStreamGetPropertyInfo failed: [%4.4s]",
                  (char *)&err );
-        return( VLC_EGENERIC );
+        return( VLC_EGENERIC ); 
+    }
+
+    if( memcmp( &P_STREAMS[i_stream], &desc, sizeof( desc ) ) != 0 ) 
+    {
+        struct { vlc_mutex_t lock; vlc_cond_t cond; } w;
+
+        vlc_cond_init( p_aout, &w.cond );
+        vlc_mutex_init( p_aout, &w.lock );
+
+        err = AudioStreamAddPropertyListener( p_option->i_sid, 0,
+                                          kAudioStreamPropertyPhysicalFormat,
+                                          StreamListener, (void *)&w );
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioStreamAddPropertyListener failed: [%4.4s]",
+                     (char *)&err );
+            vlc_mutex_destroy( &w.lock );
+            vlc_cond_destroy( &w.cond );
+            return( VLC_EGENERIC ); 
+        }
+
+        vlc_mutex_lock( &w.lock );
+
+        msg_Dbg( p_aout, STREAM_FORMAT_MSG( "setting format",
+                                            P_STREAMS[i_stream] ) );
+
+        err = AudioStreamSetProperty( p_option->i_sid, 0, 0,
+                                      kAudioStreamPropertyPhysicalFormat,
+                                      sizeof( P_STREAMS[i_stream] ),
+                                      &P_STREAMS[i_stream] ); 
+        if( err != noErr )
+        {
+            msg_Err( p_aout, "AudioStreamSetProperty failed: [%4.4s]",
+                     (char *)&err );
+            vlc_mutex_unlock( &w.lock );
+            vlc_mutex_destroy( &w.lock );
+            vlc_cond_destroy( &w.cond );
+            return( VLC_EGENERIC );
+        }
+
+        vlc_cond_wait( &w.cond, &w.lock );
+        vlc_mutex_unlock( &w.lock );
+
+        vlc_mutex_destroy( &w.lock );
+        vlc_cond_destroy( &w.cond );
+
+        if( GetStreamID( p_dev->devid, p_option->i_idx + 1, 
+                         &p_option->i_sid ) )
+        {
+            msg_Err( p_aout, "GetStreamID(%ld, %ld) failed", 
+                     p_option->i_dev, p_option->i_idx );
+            return( VLC_EGENERIC );
+        }
+
+        err = AudioStreamRemovePropertyListener( p_option->i_sid, 0,
+                kAudioStreamPropertyPhysicalFormat, StreamListener );
+        if( err != noErr )
+        {
+            msg_Err( p_aout, 
+                    "AudioStreamRemovePropertyListener failed: [%4.4s]",
+                    (char *)&err );
+
+            return( VLC_EGENERIC );
+        }
     }
 
+#undef I_STREAMS
 #undef P_STREAMS
 
-    msg_Dbg( p_aout, "getting device [%ld]", p_option->i_dev );
+    err = AudioDeviceAddPropertyListener( p_dev->devid, 0, FALSE,
+                                          kAudioDevicePropertyDeviceIsAlive,
+                                          DeviceListener, (void *)p_aout );
+    if( err != noErr )
+    {
+        msg_Err( p_aout, "AudioDeviceAddPropertyListener failed: [%4.4s]",
+                 (char *)&err );
+        return( VLC_EGENERIC );
+    } 
 
     config_PutInt( p_aout, "macosx-adev", i_option );
 
-    *p_devid = p_dev->devid;
+    p_sys->i_sel_opt = i_option;
+    p_sys->devid = p_dev->devid;
 
     return( VLC_SUCCESS );
 } 
+
+/*****************************************************************************
+ * FreeDevice 
+ *****************************************************************************/
+static void FreeDevice( aout_instance_t * p_aout ) 
+{
+    OSStatus err;
+
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    err = AudioDeviceRemovePropertyListener( p_sys->devid, 0, FALSE,
+                                             kAudioDevicePropertyDeviceIsAlive,
+                                             DeviceListener );
+    if( err != noErr )
+    {
+        msg_Err( p_aout, "AudioDeviceRemovePropertyListener failed: [%4.4s]",
+                 (char *)&err );
+    } 
+}
+
+/*****************************************************************************
+ * HardwareListener 
+ *****************************************************************************/
+static OSStatus HardwareListener( AudioHardwarePropertyID inPropertyID,
+                                  void * inClientData )
+{
+    OSStatus err = noErr;
+
+    aout_instance_t * p_aout = (aout_instance_t *)inClientData;
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    switch( inPropertyID )
+    {
+        case kAudioHardwarePropertyDevices:
+        {
+            UInt32 i_idx = 0;
+            UInt32 i_sdx = 0;
+            int i_option = -1;
+
+            if( p_sys->b_dev_alive )
+            {
+                i_idx = p_sys->p_options[p_sys->i_sel_opt].i_idx;
+                i_sdx = p_sys->p_options[p_sys->i_sel_opt].i_sdx;
+            }
+
+            FreeHardwareInfo( p_aout );
+
+            if( InitHardwareInfo( p_aout ) )
+            {
+                msg_Err( p_aout, "InitHardwareInfo failed" );
+                break;
+            }
+
+            if( p_sys->b_dev_alive )
+            {
+                UInt32 i;
+
+                for( i = 0; i < p_sys->i_options; i++ )
+                {
+                    if( p_sys->p_devices[p_sys->p_options[i].i_dev].devid ==
+                        p_sys->devid && p_sys->p_options[i].i_idx == i_idx &&
+                        p_sys->p_options[i].i_sdx == i_sdx )
+                    {
+                        i_option = i;
+                        break;
+                    }
+                }
+            }
+
+            var_Destroy( p_aout, "audio-device" );
+            InitDeviceVar( p_aout, i_option, !p_sys->b_dev_alive );
+        }
+        break;
+    }
+
+    return( err );
+}
+
+/*****************************************************************************
+ * DeviceListener 
+ *****************************************************************************/
+static OSStatus DeviceListener( AudioDeviceID inDevice,
+                                UInt32 inChannel,
+                                Boolean isInput,
+                                AudioDevicePropertyID inPropertyID,
+                                void *inClientData )
+{
+    UInt32 i_param_size;
+    OSStatus err = noErr;
+
+    aout_instance_t * p_aout = (aout_instance_t *)inClientData;
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    switch( inPropertyID )
+    {
+        case kAudioDevicePropertyDeviceIsAlive:
+        {
+            i_param_size = sizeof( p_sys->b_dev_alive );
+            err = AudioDeviceGetProperty( p_sys->devid, 0, FALSE, 
+                                          kAudioDevicePropertyDeviceIsAlive,
+                                          &i_param_size, &p_sys->b_dev_alive );
+            if( err != noErr )
+            {
+                msg_Err( p_aout, "AudioDeviceGetProperty failed: %4.4s",
+                         (char *)&err );
+            }
+        }
+        break;
+    }
+
+    return( err );
+}
+
+/*****************************************************************************
+ * StreamListener 
+ *****************************************************************************/
+static OSStatus StreamListener( AudioStreamID inStream,
+                                UInt32 inChannel,
+                                AudioDevicePropertyID inPropertyID,
+                                void * inClientData )
+{
+    OSStatus err = noErr;
+
+    struct { vlc_mutex_t lock; vlc_cond_t cond; } * w = inClientData;
+
+    switch( inPropertyID )
+    {
+        case kAudioStreamPropertyPhysicalFormat:
+            vlc_mutex_lock( &w->lock );
+            vlc_cond_signal( &w->cond );
+            vlc_mutex_unlock( &w->lock ); 
+            break;
+
+        default:
+            break;
+    }
+
+    return( err );
+}
+
+/*****************************************************************************
+ * InitDeviceVar
+ *****************************************************************************/
+static void InitDeviceVar( aout_instance_t * p_aout, int i_option,
+                           vlc_bool_t b_change )
+{ 
+    UInt32 i;
+    vlc_value_t val;
+
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    if( i_option == -1 || i_option >= (int)p_sys->i_options )
+    {
+        for( i = 0; i < p_sys->i_options; i++ )
+        {
+            if( p_sys->p_options[i].i_dev == p_sys->i_def_dev )
+            {
+                i_option = i;
+                break;
+            }
+        }
+    }
+
+    var_Create( p_aout, "audio-device", VLC_VAR_STRING | 
+                                        VLC_VAR_HASCHOICE );
+
+    for( i = 0; i < p_sys->i_options; i++ )
+    {
+        val.psz_string = p_sys->p_options[i].sz_option;
+        var_Change( p_aout, "audio-device", VLC_VAR_ADDCHOICE, &val );
+
+        if( !b_change && i == (UInt32)i_option )
+        {
+            p_sys->i_sel_opt = i;
+            var_Set( p_aout, "audio-device", val );
+            config_PutInt( p_aout, "macosx-adev", i_option );
+        }
+    }
+
+    var_AddCallback( p_aout, "audio-device", aout_ChannelsRestart,
+                     NULL );
+
+    if( b_change )
+    {
+        val.psz_string = p_sys->p_options[i_option].sz_option;
+        var_Set( p_aout, "audio-device", val );
+    }
+
+    val.b_bool = VLC_TRUE;
+    var_Set( p_aout, "intf-change", val );
+}
index a0b35dee3fc797e1a560f32a006ee3e360b0bef5..8e9aa52dc1f114f081887105349cd5b1a5d6de08 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * info.h: MacOS X info panel
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: info.h,v 1.1 2003/02/17 10:52:07 hartman Exp $
+ * Copyright (C) 2003 VideoLAN
+ * $Id: info.h,v 1.2 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Derk-Jan Hartman <thedj@users.sourceforge.net>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-#include <vlc/vlc.h>
-#include <vlc/intf.h>
-
-#import <Cocoa/Cocoa.h>
-
-
 /*****************************************************************************
  * VLCInfo interface 
  *****************************************************************************/
-@interface VLCInfo : NSObject {
+@interface VLCInfo : NSObject
+{
+    IBOutlet id o_window;
+    IBOutlet id o_view;
+    IBOutlet id o_selector;
 
-    IBOutlet id o_info_window;
-    IBOutlet id o_info_view;
-    IBOutlet id o_info_selector;
-    
-    intf_thread_t *p_intf;
-    NSMutableDictionary *o_info_strings;
+    NSMutableDictionary * o_strings;
 }
 
+- (void)updateInfo;
 - (IBAction)toggleInfoPanel:(id)sender;
 - (IBAction)showCategory:(id)sender;
-- (void)updateInfo;
 - (void)createInfoView:(input_info_category_t *)p_category;
 
-@end
\ No newline at end of file
+@end
index 8246fee898d031e68a8939985554b0d09ca6a443..470bdaa1e44b23e63ec10a26e31a9f5c063caefe 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * info.m: MacOS X info panel
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: info.m,v 1.2 2003/02/18 20:54:02 hartman Exp $
+ * Copyright (C) 2003 VideoLAN
+ * $Id: info.m,v 1.3 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Derk-Jan Hartman <thedj@users.sourceforge.net>
  *
  *****************************************************************************/
 
 #include "intf.h"
-
-#import "info.h"
+#include "info.h"
 
 /*****************************************************************************
  * VLCInfo implementation 
  *****************************************************************************/
 @implementation VLCInfo
 
+- (void)awakeFromNib
+{
+    [o_window setExcludedFromWindowsMenu: YES];
+}
+
 - (id)init
 {
     self = [super init];
 
     if( self != nil )
     {
-        p_intf = [NSApp getIntf];
-        
-        o_info_strings = [[NSMutableDictionary alloc] init];
+        o_strings = [[NSMutableDictionary alloc] init];
     }
 
     return( self );
 
 - (void)dealloc
 {
-    [o_info_strings release];
-
+    [o_strings release];
     [super dealloc];
 }
 
 - (IBAction)toggleInfoPanel:(id)sender
 {
-    if ( [o_info_window isVisible] )
+    if( [o_window isVisible] )
     {
-        [o_info_window orderOut:sender];
+        [o_window orderOut: sender];
     }
     else
     {
-        [o_info_window orderFront:sender];
+        [o_window orderFront: sender];
         [self updateInfo];
     }
 }
 
 - (IBAction)showCategory:(id)sender
 {
-    NSString *o_selected = [o_info_selector titleOfSelectedItem];
-    [o_info_view setString:(NSString *)[o_info_strings objectForKey: o_selected]];
-    [o_info_view setNeedsDisplay: YES];
+    NSString * o_title = [o_selector titleOfSelectedItem];
+    [o_view setString: [o_strings objectForKey: o_title]];
+    [o_view setNeedsDisplay: YES];
 }
 
 - (void)updateInfo
 {
-    if ( ![o_info_window isVisible] )
+    if( ![o_window isVisible] )
     {
         return;
     }
-    
+
+    intf_thread_t * p_intf = [NSApp getIntf]; 
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                        FIND_ANYWHERE );
-    
+
     if( p_playlist == NULL )
     {
-        [o_info_window orderOut:self];
         return;
     }
-    
+
+    vlc_mutex_lock( &p_playlist->object_lock );
+
     if ( p_playlist->p_input == NULL )
     {
-        [o_info_window orderOut:self];
+        vlc_mutex_unlock( &p_playlist->object_lock );
         vlc_object_release( p_playlist );
         return;
     }
 
-    [o_info_strings removeAllObjects];
-    [o_info_selector removeAllItems];
-    [o_info_view setDrawsBackground: NO];
-    [[[o_info_view superview] superview] setDrawsBackground: NO];
-    [o_info_window setExcludedFromWindowsMenu:YES];
-    
+    [o_strings removeAllObjects];
+    [o_selector removeAllItems];
+
     vlc_mutex_lock( &p_playlist->p_input->stream.stream_lock );
-    input_info_category_t *p_category = p_playlist->p_input->stream.p_info;
-    while ( p_category )
+    input_info_category_t * p_category = p_playlist->p_input->stream.p_info;
+
+    while( p_category )
     {
-        [self createInfoView: p_category ];
+        [self createInfoView: p_category];
         p_category = p_category->p_next;
     }
+
     vlc_mutex_unlock( &p_playlist->p_input->stream.stream_lock );
+    vlc_mutex_unlock( &p_playlist->object_lock );
     vlc_object_release( p_playlist );
-    
-    [o_info_selector selectItemAtIndex: 0];
-    [self showCategory:o_info_selector];
+
+    [o_selector selectItemAtIndex: 0];
+    [self showCategory: o_selector];
 }
 
 - (void)createInfoView:(input_info_category_t *)p_category
 {
-    /* Add a catecory */
-    NSString *title = [NSString stringWithCString: p_category->psz_name];
-    [o_info_selector addItemWithTitle: title];
-    
-    /* Create the textfield content */
-    NSMutableString *catString = [NSMutableString string];
-    
+    NSString * o_title;
+    NSMutableString * o_content;
+    input_info_t * p_info;
+
+    /* Add a category */
+    o_title = [NSString stringWithCString: p_category->psz_name];
+    [o_selector addItemWithTitle: o_title];
+
+    /* Create empty content string */
+    o_content = [NSMutableString string];
+
     /* Add the fields */
-    input_info_t *p_info = p_category->p_info;
-    while ( p_info )
+    p_info = p_category->p_info;
+
+    while( p_info )
     {
-        [catString appendFormat: @"%s: %s\n\n", p_info->psz_name, p_info->psz_value];
+        [o_content appendFormat: @"%s: %s\n\n", p_info->psz_name,
+                                                p_info->psz_value]; 
         p_info = p_info->p_next;
     }
-    [o_info_strings setObject: catString forKey: title];
+
+    [o_strings setObject: o_content forKey: o_title];
 }
 
 @end
 {
     BOOL bEnabled = TRUE;
 
+    intf_thread_t * p_intf = [NSApp getIntf];
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                                        FIND_ANYWHERE );
 
     return( bEnabled );
 }
 
-@end
\ No newline at end of file
+@end
index 6554e6fcee34801e7fea180064eb59e954549fce..ada4ad8b5f6bb6f73f19045afb632443aa86f643 100644 (file)
@@ -2,7 +2,7 @@
  * intf.m: MacOS X interface plugin
  *****************************************************************************
  * Copyright (C) 2002-2003 VideoLAN
- * $Id: intf.m,v 1.60 2003/02/19 14:49:25 hartman Exp $
+ * $Id: intf.m,v 1.61 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Christophe Massiot <massiot@via.ecp.fr>
@@ -435,15 +435,6 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg )
 
         if( p_playlist != NULL )
         {
-            vlc_value_t val;
-
-            if( var_Get( (vlc_object_t *)p_playlist, "intf-change", &val )
-                >= 0 && val.b_bool )
-            {
-                p_intf->p_sys->b_playlist_update = 1;
-                p_intf->p_sys->b_intf_update = VLC_TRUE;
-            }
-            
             vlc_mutex_lock( &p_playlist->object_lock );
             
             [self manage: p_playlist];
@@ -465,8 +456,17 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg )
 
 - (void)manage:(playlist_t *)p_playlist
 {
+    vlc_value_t val;
+
     intf_thread_t * p_intf = [NSApp getIntf];
 
+    if( var_Get( (vlc_object_t *)p_playlist, "intf-change", &val ) >= 0 &&
+        val.b_bool )
+    {
+        p_intf->p_sys->b_playlist_update = VLC_TRUE;
+        p_intf->p_sys->b_intf_update = VLC_TRUE;
+    }
+
 #define p_input p_playlist->p_input
 
     if( p_input )
@@ -508,8 +508,10 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg )
                     p_intf->p_sys->b_aout_update = 1;
                     b_need_menus = VLC_TRUE;
                 }
+
                 vlc_object_release( (vlc_object_t *)p_aout );
             }
+
             aout_VolumeGet( p_intf, &i_volume );
             p_intf->p_sys->b_mute = ( i_volume == 0 );
 
@@ -578,15 +580,6 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg )
             vout_Destroy( p_vout );
             vlc_mutex_lock( &p_playlist->object_lock );
         }
-
-        aout_instance_t * p_aout = vlc_object_find( p_intf, VLC_OBJECT_AOUT,
-                                                            FIND_ANYWHERE );
-        if( p_aout != NULL )
-        {
-            vlc_object_detach( (vlc_object_t *)p_aout );
-            vlc_object_release( (vlc_object_t *)p_aout );
-            aout_Delete( p_aout ); 
-        }
     }
 
     p_intf->p_sys->b_intf_update = VLC_TRUE;
@@ -610,52 +603,47 @@ int ExecuteOnMainThread( id target, SEL sel, void * p_arg )
         return;
     }
 
-    vlc_mutex_lock( &p_playlist->object_lock );
-    
     if ( p_intf->p_sys->b_playlist_update )
     {
         vlc_value_t val;
-        val.b_bool = 0;
 
+        val.b_bool = 0;
         var_Set( (vlc_object_t *)p_playlist, "intf-change", val );
+
         [o_playlist playlistUpdated];
+
         p_intf->p_sys->b_playlist_update = VLC_FALSE;
     }
 
-#define p_input p_playlist->p_input
-
-    if( p_input != NULL )
-    {
-        vlc_mutex_lock( &p_input->stream.stream_lock );
-    }
-    
     if( p_intf->p_sys->b_current_title_update )
     {
-        id o_awindow = [NSApp keyWindow];
-        NSArray *o_windows = [NSApp windows];
-        NSEnumerator *o_enumerator = [o_windows objectEnumerator];
+        id o_vout_wnd;
+
+        NSEnumerator * o_enum = [[NSApp windows] objectEnumerator];
         
-        while ((o_awindow = [o_enumerator nextObject]))
+        while( ( o_vout_wnd = [o_enum nextObject] ) )
         {
-            if( [[o_awindow className] isEqualToString: @"VLCWindow"] )
+            if( [[o_vout_wnd className] isEqualToString: @"VLCWindow"] )
             {
-                vlc_mutex_unlock( &p_playlist->object_lock );
-                [o_awindow updateTitle];
-                vlc_mutex_lock( &p_playlist->object_lock );
+                [o_vout_wnd updateTitle];
             }
         }
-        vlc_mutex_unlock( &p_playlist->object_lock );
-        [o_playlist updateState];
-        vlc_mutex_lock( &p_playlist->object_lock );
-        if( p_input != NULL )
-        {
-            vlc_mutex_unlock( &p_input->stream.stream_lock );
-            [o_info updateInfo];
-            vlc_mutex_lock( &p_input->stream.stream_lock );
-        }
+
+        [o_playlist updateRowSelection];
+        [o_info updateInfo];
+
         p_intf->p_sys->b_current_title_update = FALSE;
     }
 
+    vlc_mutex_lock( &p_playlist->object_lock );
+
+#define p_input p_playlist->p_input
+
+    if( p_input != NULL )
+    {
+        vlc_mutex_lock( &p_input->stream.stream_lock );
+    }
+
     if( p_intf->p_sys->b_intf_update )
     {
         vlc_bool_t b_input = VLC_FALSE;
index c6e18a8fdfbb21b3b612e34c86ee9c41ab4e2401..696de45d3521fc53ebde9f013c5fe852f3c0a242 100644 (file)
@@ -2,7 +2,7 @@
  * macosx.m: MacOS X plugin for vlc
  *****************************************************************************
  * Copyright (C) 2001-2003 VideoLAN
- * $Id: macosx.m,v 1.3 2003/02/20 01:52:46 sigmunau Exp $
+ * $Id: macosx.m,v 1.4 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Colin Delacroix <colin@zoy.org>
  *          Eugenio Jarosiewicz <ej0@cise.ufl.edu>
@@ -56,7 +56,7 @@ vlc_module_begin();
         set_capability( "interface", 100 );
         set_callbacks( E_(OpenIntf), E_(CloseIntf) );
     add_submodule();
-        set_capability( "video output", 100 );
+        set_capability( "video output", 200 );
         set_callbacks( E_(OpenVideo), E_(CloseVideo) );
         add_category_hint( N_("Video"), NULL, VLC_FALSE );
         add_integer( "macosx-vdev", 0, NULL, VDEV_TEXT, VDEV_TEXT, VLC_FALSE );
@@ -64,6 +64,6 @@ vlc_module_begin();
         set_capability( "audio output", 100 );
         set_callbacks( E_(OpenAudio), E_(CloseAudio) );
         add_category_hint( N_("Audio"), NULL, VLC_FALSE );
-        add_integer( "macosx-adev", 0, NULL, ADEV_TEXT, ADEV_TEXT, VLC_FALSE );
+        add_integer( "macosx-adev", -1, NULL, ADEV_TEXT, ADEV_TEXT, VLC_FALSE );
 vlc_module_end();
 
index 2d97487fadff055454d0ccfe35e04f923b97ccd1..c63effa6b06e06e5511d89dc115c15067fe4d37e 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * playlist.h: MacOS X interface plugin
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: playlist.h,v 1.5 2003/02/13 14:16:41 hartman Exp $
+ * Copyright (C) 2002-2003 VideoLAN
+ * $Id: playlist.h,v 1.6 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *          Derk-Jan Hartman <thedj@users.sourceforge.net>
@@ -56,7 +56,8 @@
 - (IBAction)selectAll:(id)sender;
 
 - (void)appendArray:(NSArray*)o_array atPos:(int)i_pos enqueue:(BOOL)b_enqueue;
+
+- (void)updateRowSelection;
 - (void)playlistUpdated;
-- (void)updateState;
 
 @end
index 4af3cf5ecce30672d2e3be612d13c4bca3496553..5a009b425395230d7515e781050aae8f34fd86b3 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * playlist.m: MacOS X interface plugin
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: playlist.m,v 1.11 2003/02/13 14:16:41 hartman Exp $
+ * Copyright (C) 2002-2003 VideoLAN
+ * $Id: playlist.m,v 1.12 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *
@@ -65,7 +65,7 @@
     {
         case ' ':
             vlc_mutex_lock( &p_playlist->object_lock );
-            if( p_playlist != NULL && p_playlist->p_input != NULL )
+            if( p_playlist->p_input != NULL )
             {
                 input_SetStatus( p_playlist->p_input, INPUT_STATUS_PAUSE );
             }
     [o_table_view reloadData];
 }
 
-- (void)updateState
+- (void)updateRowSelection
 {
     int i_row;
 
     {
         return;
     }
-    
+
+    vlc_mutex_lock( &p_playlist->object_lock );    
     i_row = p_playlist->i_index;
+    vlc_mutex_unlock( &p_playlist->object_lock );
     vlc_object_release( p_playlist );
-    
+
     [o_table_view selectRow: i_row byExtendingSelection: NO];
     [o_table_view scrollRowToVisible: i_row];
-    
+
     vout_thread_t * p_vout = vlc_object_find( p_intf, VLC_OBJECT_VOUT,
-                                                          FIND_ANYWHERE );
+                                                      FIND_ANYWHERE );
 
-    if ( p_vout == NULL )
+    if( p_vout == NULL || !p_vout->b_fullscreen )
     {
-        [[NSApp keyWindow] makeFirstResponder:o_table_view];
-        return;
+        [[NSApp keyWindow] makeFirstResponder: o_table_view];
     }
-    else if ( !p_vout->b_fullscreen )
+
+    if( p_vout != NULL )
     {
-        [[NSApp keyWindow] makeFirstResponder:o_table_view];
+        vlc_object_release( (vlc_object_t *)p_vout );
     }
-    vlc_object_release( (vlc_object_t *)p_vout );
 }
 
 @end
     int i_count = 0;
     intf_thread_t * p_intf = [NSApp getIntf];
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
+                                                       FIND_ANYWHERE );
 
     if( p_playlist != NULL )
     {
+        vlc_mutex_lock( &p_playlist->object_lock );
         i_count = p_playlist->i_size;
+        vlc_mutex_unlock( &p_playlist->object_lock );
         vlc_object_release( p_playlist );
     }
 
index cb9089f7a1d93af2966b392c64efa815e4d56b3c..eb980e7c11b96e3622aca5f5d95a14b994ef3f8f 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * prefs.h: MacOS X plugin for vlc
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: prefs.h,v 1.3 2003/02/21 02:45:21 hartman Exp $
+ * Copyright (C) 2002-2003 VideoLAN
+ * $Id: prefs.h,v 1.4 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net> 
  *
index 6b41bc431d93f982cb3bd200cc0dd24186acfdba..79b9c28106a5071bcc63d6194a2f5a8df4d3ec15 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * prefs.m: MacOS X plugin for vlc
  *****************************************************************************
- * Copyright (C) 2002 VideoLAN
- * $Id: prefs.m,v 1.15 2003/02/21 02:45:21 hartman Exp $
+ * Copyright (C) 2002-2003 VideoLAN
+ * $Id: prefs.m,v 1.16 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
  *
 
     if( p_item ) do
     {
-        if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ))
+        if( p_item->b_advanced && !config_GetInt( p_intf, "advanced" ) )
         {
             continue;
         }
 {
     id o_vlc_control;
     NSEnumerator *o_enum;
-    BOOL b_advanced_change = FALSE;
+    BOOL b_adv_change = FALSE;
     
     NSWindow *o_pref_panel = [[sender superview] window];
     NSString *o_module_name = [[o_pref_panel toolbar] identifier];
                     psz_value = (char *)[o_value lossyCString];
     
                     config_PutPsz( p_intf, psz_name,
-                                *psz_value ? psz_value : NULL );
+                                   *psz_value ? psz_value : NULL );
                 }
                 break;
     
             case CONFIG_ITEM_BOOL:
                 {
                     int i_value = [o_vlc_control intValue];
-                    if ( !strcmp( psz_name, "advanced" ) && ( config_GetInt( p_intf, "advanced" ) != i_value ) )
+
+                    if( !strcmp( psz_name, "advanced" ) && 
+                        ( config_GetInt( p_intf, "advanced" ) != i_value ) )
                     {
-                        b_advanced_change = TRUE;
+                        b_adv_change = TRUE;
                     }
+
                     config_PutInt( p_intf, psz_name, i_value );
                 }
                 break;
         config_SaveConfigFile( p_intf, NULL );
     }
     
-    if ( [[sender title] isEqualToString: _NS("Apply")] && !b_advanced_change )
-    {
-        ;
-    }
-    else
+    if( ![[sender title] isEqualToString: _NS("Apply")] || b_adv_change )
     {
         [o_pref_panel close];
 
             [self performSelectorOnMainThread: @selector(destroyPrefPanel:)
                                             withObject: o_module_name
                                             waitUntilDone: YES];
-            if ( [[sender title] isEqualToString: _NS("Apply")] && b_advanced_change )
-            {
-                [self createPrefPanel:@"main"];
-            }
         }
         else
         {
                     target: self selector: @selector(destroyPrefPanel:)
                     userInfo: o_module_name repeats: NO];
         }
+
+        if( [[sender title] isEqualToString: _NS("Apply")] && b_adv_change )
+        {
+            [self createPrefPanel: o_module_name];
+        }
     }
 }
 
index 3670d3f3bc4a3e7ef5314137225fb78bf7691dc9..dbf0ab35808f2f484ddd99da878eb9cf503d077a 100644 (file)
@@ -2,7 +2,7 @@
  * vout.m: MacOS X video output plugin
  *****************************************************************************
  * Copyright (C) 2001-2003 VideoLAN
- * $Id: vout.m,v 1.34 2003/02/15 12:57:51 hartman Exp $
+ * $Id: vout.m,v 1.35 2003/02/23 05:53:53 jlj Exp $
  *
  * Authors: Colin Delacroix <colin@zoy.org>
  *          Florian G. Pflug <fgp@phlo.org>
@@ -819,10 +819,11 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
 
 - (void)updateTitle
 {
-    NSMutableString *o_title;
+    NSMutableString * o_title;
+
     intf_thread_t * p_intf = [NSApp getIntf];
     playlist_t * p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
-                                               FIND_ANYWHERE );
+                                                       FIND_ANYWHERE );
     
     if( p_playlist == NULL )
     {
@@ -836,11 +837,13 @@ static void QTFreePicture( vout_thread_t *p_vout, picture_t *p_pic )
 
     vlc_object_release( p_playlist );
 
-    if (o_title)
+    if( o_title != nil )
     {
-        NSRange prefixrange = [o_title rangeOfString: @"file:"];
-        if ( prefixrange.location != NSNotFound )
-            [o_title deleteCharactersInRange: prefixrange];
+        NSRange prefix_range = [o_title rangeOfString: @"file:"];
+        if( prefix_range.location != NSNotFound )
+        {
+            [o_title deleteCharactersInRange: prefix_range];
+        }
 
         [self setTitleWithRepresentedFilename: o_title];
     }