]> git.sesse.net Git - vlc/commitdiff
aout: add distinct start/stop callbacks (refs #4787, refs #7601)
authorRémi Denis-Courmont <remi@remlab.net>
Sat, 20 Oct 2012 17:27:48 +0000 (20:27 +0300)
committerRémi Denis-Courmont <remi@remlab.net>
Wed, 31 Oct 2012 18:21:00 +0000 (20:21 +0200)
This would enable the input manager to hold an audio output plugin at
all times. Then it would be possible to keep track of output devices,
volume, policy and (JACK) routing continuously. For this to work,
outputs will need to be patched so that device selection and volume
handling works even when playing back.

Note though that this commit only introduces the change in the
audio_output_t interface; it does not implement the features above.

19 files changed:
include/vlc_aout.h
modules/audio_output/adummy.c
modules/audio_output/alsa.c
modules/audio_output/amem.c
modules/audio_output/audioqueue.c
modules/audio_output/audiotrack.c
modules/audio_output/auhal.c
modules/audio_output/directx.c
modules/audio_output/file.c
modules/audio_output/jack.c
modules/audio_output/kai.c
modules/audio_output/opensles_android.c
modules/audio_output/oss.c
modules/audio_output/packet.c
modules/audio_output/pulse.c
modules/audio_output/sndio.c
modules/audio_output/wasapi.c
modules/audio_output/waveout.c
src/audio_output/output.c

index bc8fbe1c9784e5904840f6dc3707b9cd7574272e..6bdd4f865f70b0f2a95804eb1796871d903c7fdb 100644 (file)
@@ -140,10 +140,9 @@ struct audio_output
 {
     VLC_COMMON_MEMBERS
 
-    audio_sample_format_t format; /**< Output format (plugin can modify it
-        only when succesfully probed and not afterward) */
-
     struct aout_sys_t *sys; /**< Output plugin private data */
+    int (*start) (audio_output_t *, audio_sample_format_t *);
+    void (*stop) (audio_output_t *);
     void (*play)(audio_output_t *, block_t *, mtime_t *); /**< Play callback
         - queue a block for playback */
     void (*pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume
@@ -277,6 +276,7 @@ struct aout_fifo_t
 typedef struct
 {
     vlc_mutex_t lock;
+    audio_sample_format_t format;
     aout_fifo_t partial; /**< Audio blocks before packetization */
     aout_fifo_t fifo; /**< Packetized audio blocks */
     mtime_t pause_date; /**< Date when paused or VLC_TS_INVALID */
@@ -285,7 +285,7 @@ typedef struct
     bool starving; /**< Whether currently starving (to limit error messages) */
 } aout_packet_t;
 
-VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned);
+VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned, const audio_sample_format_t *);
 VLC_DEPRECATED void aout_PacketDestroy(audio_output_t *);
 
 VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *, mtime_t *);
index 56659fff2216f94a95b90b0540f08a58723f5125..887947b93b5567393509cb3234e29e113fb1414d 100644 (file)
@@ -49,25 +49,30 @@ static void Play( audio_output_t *aout, block_t *block, mtime_t *drift )
     (void) drift;
 }
 
-static int Open( vlc_object_t * p_this )
+static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-    audio_output_t * p_aout = (audio_output_t *)p_this;
-
-    p_aout->play = Play;
-    p_aout->pause = NULL;
-    p_aout->flush = NULL;
-    p_aout->volume_set = NULL;
-    p_aout->mute_set = NULL;
-
-    if( AOUT_FMT_SPDIF( &p_aout->format )
-     && var_InheritBool( p_this, "spdif" ) )
+    if (AOUT_FMT_SPDIF(fmt) && var_InheritBool(aout, "spdif"))
     {
-        p_aout->format.i_format = VLC_CODEC_SPDIFL;
-        p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        p_aout->format.i_frame_length = A52_FRAME_NB;
+        fmt->i_format = VLC_CODEC_SPDIFL;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
     }
     else
-        p_aout->format.i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
+        fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
+
+    return VLC_SUCCESS;
+}
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
 
+    aout->start = Start;
+    aout->play = Play;
+    aout->pause = NULL;
+    aout->flush = NULL;
+    aout->stop = NULL;
+    aout->volume_set = NULL;
+    aout->mute_set = NULL;
     return VLC_SUCCESS;
 }
index e77cb98fa2228be5042d445988f00bdb8be6e3cd..0acd1389324a65c799df186cd194bf2489e04a10 100644 (file)
@@ -46,6 +46,7 @@ struct aout_sys_t
     void (*reorder) (void *, size_t, unsigned);
     float soft_gain;
     bool soft_mute;
+    audio_sample_format_t format;
 };
 
 #include "volume.h"
@@ -159,9 +160,9 @@ static void Flush (audio_output_t *, bool);
 static void Reorder71 (void *, size_t, unsigned);
 
 /** Initializes an ALSA playback stream */
-static int Open (vlc_object_t *obj)
+static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
 
     /* Get device name */
     char *device = var_InheritString (aout, "alsa-audio-device");
@@ -169,7 +170,7 @@ static int Open (vlc_object_t *obj)
         return VLC_ENOMEM;
 
     snd_pcm_format_t pcm_format; /* ALSA sample format */
-    vlc_fourcc_t fourcc = aout->format.i_format;
+    vlc_fourcc_t fourcc = fmt->i_format;
     bool spdif = false;
 
     switch (fourcc)
@@ -223,7 +224,7 @@ static int Open (vlc_object_t *obj)
             pcm_format = SND_PCM_FORMAT_U8;
             break;
         default:
-            if (AOUT_FMT_SPDIF(&aout->format))
+            if (AOUT_FMT_SPDIF(fmt))
                 spdif = var_InheritBool (aout, "spdif");
             if (spdif)
             {
@@ -246,14 +247,14 @@ static int Open (vlc_object_t *obj)
     /* ALSA channels */
     /* XXX: maybe this should be shared with other dumb outputs */
     uint32_t map = var_InheritInteger (aout, "alsa-audio-channels");
-    map &= aout->format.i_physical_channels;
+    map &= fmt->i_physical_channels;
     if (unlikely(map == 0)) /* WTH? */
         map = AOUT_CHANS_STEREO;
 
     unsigned channels = popcount (map);
-    if (channels < aout_FormatNbChannels (&aout->format))
+    if (channels < aout_FormatNbChannels (fmt))
         msg_Dbg (aout, "downmixing from %u to %u channels",
-                 aout_FormatNbChannels (&aout->format), channels);
+                 aout_FormatNbChannels (fmt), channels);
     else
         msg_Dbg (aout, "keeping %u channels", channels);
 
@@ -264,7 +265,7 @@ static int Open (vlc_object_t *obj)
     {
         unsigned aes3;
 
-        switch (aout->format.i_rate)
+        switch (fmt->i_rate)
         {
 #define FS(freq) \
             case freq: aes3 = IEC958_AES3_CON_FS_ ## freq; break;
@@ -287,15 +288,6 @@ static int Open (vlc_object_t *obj)
             return VLC_ENOMEM;
     }
 
-    /* Allocate structures */
-    aout_sys_t *sys = malloc (sizeof (*sys));
-    if (unlikely(sys == NULL))
-    {
-        free (device);
-        return VLC_ENOMEM;
-    }
-    aout->sys = sys;
-
     /* Open the device */
     snd_pcm_t *pcm;
     /* VLC always has a resampler. No need for ALSA's. */
@@ -332,7 +324,6 @@ static int Open (vlc_object_t *obj)
                       _("The audio device \"%s\" could not be used:\n%s."),
                       device, snd_strerror (val));
         free (device);
-        free (sys);
         return VLC_EGENERIC;
     }
     sys->pcm = pcm;
@@ -412,16 +403,15 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Set sample rate */
-    unsigned rate = aout->format.i_rate;
+    unsigned rate = fmt->i_rate;
     val = snd_pcm_hw_params_set_rate_near (pcm, hw, &rate, NULL);
     if (val)
     {
         msg_Err (aout, "cannot set sample rate: %s", snd_strerror (val));
         goto error;
     }
-    if (aout->format.i_rate != rate)
-        msg_Dbg (aout, "resampling from %d Hz to %d Hz",
-                 aout->format.i_rate, rate);
+    if (fmt->i_rate != rate)
+        msg_Dbg (aout, "resampling from %d Hz to %d Hz", fmt->i_rate, rate);
 
     /* Set buffer size */
     param = AOUT_MAX_ADVANCE_TIME;
@@ -497,29 +487,26 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Setup audio_output_t */
-    aout->format.i_format = fourcc;
-    aout->format.i_rate = rate;
+    fmt->i_format = fourcc;
+    fmt->i_rate = rate;
     sys->reorder = NULL;
     if (spdif)
     {
-        aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        aout->format.i_frame_length = A52_FRAME_NB;
-        aout->volume_set = NULL;
-        aout->mute_set = NULL;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
     }
     else
     {
-        aout->format.i_original_channels =
-        aout->format.i_physical_channels = map;
+        fmt->i_original_channels =
+        fmt->i_physical_channels = map;
         switch (popcount (map))
         {
             case 8:
                 sys->reorder = Reorder71;
                 break;
         }
-
-        aout_SoftVolumeInit (aout);
     }
+    sys->format = *fmt;
 
     aout->play = Play;
     if (snd_pcm_hw_params_can_pause (hw))
@@ -535,13 +522,13 @@ static int Open (vlc_object_t *obj)
     {
         vlc_value_t text;
 
-        var_Create (obj, "audio-device", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
+        var_Create (aout, "audio-device", VLC_VAR_STRING | VLC_VAR_HASCHOICE);
         text.psz_string = _("Audio Device");
-        var_Change (obj, "audio-device", VLC_VAR_SETTEXT, &text, NULL);
+        var_Change (aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL);
 
-        GetDevices (obj, device);
+        GetDevices (VLC_OBJECT(aout), device);
     }
-    var_AddCallback (obj, "audio-device", DeviceChanged, NULL);
+    var_AddCallback (aout, "audio-device", DeviceChanged, NULL);
 
     free (device);
     return 0;
@@ -549,7 +536,6 @@ static int Open (vlc_object_t *obj)
 error:
     snd_pcm_close (pcm);
     free (device);
-    free (sys);
     return VLC_EGENERIC;
 }
 
@@ -563,7 +549,7 @@ static void Play (audio_output_t *aout, block_t *block,
 
     if (sys->reorder != NULL)
         sys->reorder (block->p_buffer, block->i_nb_samples,
-                      aout->format.i_bitspersample / 8);
+                      sys->format.i_bitspersample / 8);
 
     snd_pcm_t *pcm = sys->pcm;
     snd_pcm_sframes_t frames;
@@ -571,19 +557,19 @@ static void Play (audio_output_t *aout, block_t *block,
 
     if (snd_pcm_delay (pcm, &frames) == 0)
     {
-        mtime_t delay = frames * CLOCK_FREQ / aout->format.i_rate;
+        mtime_t delay = frames * CLOCK_FREQ / sys->format.i_rate;
         delay += mdate () - block->i_pts;
 
         if (state != SND_PCM_STATE_RUNNING)
         {
             if (delay < 0)
             {
-                if (aout->format.i_format != VLC_CODEC_SPDIFL)
+                if (sys->format.i_format != VLC_CODEC_SPDIFL)
                 {
-                    frames = (delay * aout->format.i_rate) / -CLOCK_FREQ;
+                    frames = (delay * sys->format.i_rate) / -CLOCK_FREQ;
                     msg_Dbg (aout, "prepending %ld zeroes", frames);
 
-                    void *z = calloc (frames, aout->format.i_bytes_per_frame);
+                    void *z = calloc (frames, sys->format.i_bytes_per_frame);
                     if (likely(z != NULL))
                     {
                         snd_pcm_writei (pcm, z, frames);
@@ -677,18 +663,16 @@ static void Flush (audio_output_t *aout, bool wait)
 /**
  * Releases the audio output.
  */
-static void Close (vlc_object_t *obj)
+static void Stop (audio_output_t *aout)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
-    snd_pcm_t *pcm = aout->sys->pcm;
+    snd_pcm_t *pcm = sys->pcm;
 
-    var_DelCallback (obj, "audio-device", DeviceChanged, NULL);
-    var_Destroy (obj, "audio-device");
+    var_DelCallback (aout, "audio-device", DeviceChanged, NULL);
+    var_Destroy (aout, "audio-device");
 
     snd_pcm_drop (pcm);
     snd_pcm_close (pcm);
-    free (sys);
 }
 
 /**
@@ -837,3 +821,25 @@ static void GetDevices(vlc_object_t *obj, const char *prefs_dev)
     }
     var_Change(obj, "audio-device", VLC_VAR_SETVALUE, &val, NULL);
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc (sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout_SoftVolumeInit (aout);
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
+}
index 23dc23ac1674141de0210c3b2e0110f04e9e96ae..68ed27132d013b4a4be8bcf8a3a51f044c8dfab6 100644 (file)
@@ -55,13 +55,22 @@ vlc_module_end ()
 struct aout_sys_t
 {
     void *opaque;
+    int (*setup) (void **, char *, unsigned *, unsigned *);
+    union
+    {
+        void (*cleanup) (void *opaque);
+        struct
+        {
+             unsigned rate:18;
+             unsigned channels:14;
+        };
+    };
     void (*play) (void *opaque, const void *data, unsigned count, int64_t pts);
     void (*pause) (void *opaque, int64_t pts);
     void (*resume) (void *opaque, int64_t pts);
     void (*flush) (void *opaque);
     void (*drain) (void *opaque);
     int (*set_volume) (void *opaque, float vol, bool mute);
-    void (*cleanup) (void *opaque);
     float volume;
     bool mute;
 };
@@ -132,109 +141,116 @@ static int SoftMuteSet (audio_output_t *aout, bool mute)
     return 0;
 }
 
-typedef int (*vlc_audio_format_cb) (void **, char *, unsigned *, unsigned *);
-
-static int Open (vlc_object_t *obj)
+static int Start (audio_output_t *aout, audio_sample_format_t *fmt)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
-    aout_sys_t *sys = malloc (sizeof (*sys));
-    if (unlikely(sys == NULL))
-        return VLC_ENOMEM;
-
-    aout->sys = sys;
-    sys->opaque = var_InheritAddress (obj, "amem-data");
-    sys->play = var_InheritAddress (obj, "amem-play");
-    sys->pause = var_InheritAddress (obj, "amem-pause");
-    sys->resume = var_InheritAddress (obj, "amem-resume");
-    sys->flush = var_InheritAddress (obj, "amem-flush");
-    sys->drain = var_InheritAddress (obj, "amem-drain");
-    sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
-    sys->cleanup = NULL; /* defer */
-    sys->volume = 1.;
-    sys->mute = false;
-    if (sys->play == NULL)
-        goto error;
-
-    vlc_audio_format_cb setup = var_InheritAddress (obj, "amem-setup");
+    aout_sys_t *sys = aout->sys;
     char format[5] = "S16N";
-    unsigned rate, channels;
+    unsigned channels;
 
-    if (setup != NULL)
+    if (sys->setup != NULL)
     {
-        rate = aout->format.i_rate;
-        channels = aout_FormatNbChannels(&aout->format);
+        channels = aout_FormatNbChannels(fmt);
 
-        if (setup (&sys->opaque, format, &rate, &channels))
-            goto error;
-        /* Only call this callback if setup succeeded */
-        sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
+        if (sys->setup (&sys->opaque, format, &fmt->i_rate, &channels))
+            return VLC_EGENERIC;
     }
     else
     {
-        rate = var_InheritInteger (obj, "amem-rate");
-        channels = var_InheritInteger (obj, "amem-channels");
+        fmt->i_rate = sys->rate;
+        channels = sys->channels;
     }
 
-    if (rate == 0 || rate > 192000
+    if (fmt->i_rate == 0 || fmt->i_rate > 192000
      || channels == 0 || channels > AOUT_CHAN_MAX)
-        goto error;
+        return VLC_EGENERIC;
 
     /* TODO: amem-format */
     if (strcmp(format, "S16N"))
     {
         msg_Err (aout, "format not supported");
-        goto error;
+        return VLC_EGENERIC;
     }
 
     /* channel mapping */
     switch (channels)
     {
         case 1:
-            aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
             break;
         case 2:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+            fmt->i_physical_channels = AOUT_CHANS_2_0;
             break;
         case 3:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_LFE;
+            fmt->i_physical_channels = AOUT_CHANS_2_1;
             break;
         case 4:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
-                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
+            fmt->i_physical_channels = AOUT_CHANS_4_0;
             break;
         case 5:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
-                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
+            fmt->i_physical_channels = AOUT_CHANS_5_0;
             break;
         case 6:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
-                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
+            fmt->i_physical_channels = AOUT_CHANS_5_1;
             break;
         case 7:
-            aout->format.i_physical_channels =
+            fmt->i_physical_channels =
                 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                 AOUT_CHAN_REARCENTER | AOUT_CHAN_MIDDLELEFT |
                 AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
             break;
         case 8:
-            aout->format.i_physical_channels =
-                AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
-                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
-                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE;
+            fmt->i_physical_channels = AOUT_CHANS_7_1;
             break;
         default:
             assert(0);
     }
 
-    aout->format.i_format = VLC_CODEC_S16N;
-    aout->format.i_rate = rate;
-    aout->format.i_original_channels = aout->format.i_physical_channels;
+    fmt->i_format = VLC_CODEC_S16N;
+    fmt->i_original_channels = fmt->i_physical_channels;
+    return VLC_SUCCESS;
+}
+
+static void Stop (audio_output_t *aout)
+{
+    aout_sys_t *sys = aout->sys;
+
+    if (sys->cleanup != NULL)
+        sys->cleanup (sys->opaque);
+}
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc (sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
 
+    aout->sys = sys;
+    sys->opaque = var_InheritAddress (obj, "amem-data");
+    sys->setup = var_InheritAddress (obj, "amem-setup");
+    if (sys->setup != NULL)
+        sys->cleanup = var_InheritAddress (obj, "amem-cleanup");
+    else
+    {
+        sys->rate = var_InheritInteger (obj, "amem-rate");
+        sys->channels = var_InheritInteger (obj, "amem-channels");
+    }
+    sys->play = var_InheritAddress (obj, "amem-play");
+    sys->pause = var_InheritAddress (obj, "amem-pause");
+    sys->resume = var_InheritAddress (obj, "amem-resume");
+    sys->flush = var_InheritAddress (obj, "amem-flush");
+    sys->drain = var_InheritAddress (obj, "amem-drain");
+    sys->set_volume = var_InheritAddress (obj, "amem-set-volume");
+    sys->volume = 1.;
+    sys->mute = false;
+    if (sys->play == NULL)
+    {
+        free (sys);
+        return VLC_EGENERIC;
+    }
+
+    aout->start = Start;
+    aout->stop = Stop;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
@@ -249,10 +265,6 @@ static int Open (vlc_object_t *obj)
         aout->mute_set = SoftMuteSet;
     }
     return VLC_SUCCESS;
-
-error:
-    Close (obj);
-    return VLC_EGENERIC;
 }
 
 static void Close (vlc_object_t *obj)
@@ -260,7 +272,5 @@ static void Close (vlc_object_t *obj)
     audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
 
-    if (sys->cleanup != NULL)
-        sys->cleanup (sys->opaque);
     free (sys);
 }
index 9c4777b6133b143ebd3ea6d192f3eaeac3df9977..b3eb68faefc47a0eca545140bc8ad0bd77f8ef1a 100644 (file)
@@ -79,11 +79,10 @@ vlc_module_end ()
  * Open: open the audio device
  *****************************************************************************/
 
-static int Open ( vlc_object_t *p_this )
+static int Start( audio_output_t *aout, audio_sample_format_t *restrict fmt )
 {
     audio_output_t *p_aout = (audio_output_t *)p_this;
-    struct aout_sys_t *p_sys = malloc(sizeof(aout_sys_t));
-    p_aout->sys = p_sys;
+    aout_sys_t *p_sys = aout->sys;
 
     OSStatus status = 0;
 
@@ -120,13 +119,10 @@ static int Open ( vlc_object_t *p_this )
         AudioQueueCallback(NULL, p_sys->audioQueue, buffer);
     }
 
-    /* Volume is entirely done in software. */
-    aout_SoftVolumeInit( p_aout );
-
-    p_aout->format.i_format = VLC_CODEC_S16L;
-    p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
-    p_aout->format.i_rate = 44100;
-    aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE);
+    fmt->i_format = VLC_CODEC_S16L;
+    fmt->i_physical_channels = AOUT_CHANS_STEREO;
+    fmt->i_rate = 44100;
+    aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE, fmt);
     p_aout->play = aout_PacketPlay;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
@@ -156,9 +152,8 @@ static block_t *aout_FifoPop2( aout_fifo_t * p_fifo )
 /*****************************************************************************
  * Close: close the audio device
  *****************************************************************************/
-static void Close ( vlc_object_t *p_this )
+static void Stop ( audio_output_t *p_aout )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     struct aout_sys_t * p_sys = p_aout->sys;
 
     msg_Dbg(p_aout, "Stopping AudioQueue");
@@ -166,7 +161,6 @@ static void Close ( vlc_object_t *p_this )
     msg_Dbg(p_aout, "Disposing of AudioQueue");
     AudioQueueDispose(p_sys->audioQueue, false);
     aout_PacketDestroy(p_aout);
-    free (p_sys);
 }
 
 void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
@@ -195,3 +189,25 @@ void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferR
     }
     AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc(sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout_SoftVolumeInit(aout);
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
+}
index d6a63979b81cfa90c34e01c01d534ef8a6aeb08d..f039ae93913393ea0b19b87d8c1e272e4d76baa1 100644 (file)
@@ -174,28 +174,16 @@ static void *InitLibrary(struct aout_sys_t *p_sys)
     return p_library;
 }
 
-static int Open(vlc_object_t *p_this)
+static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-    struct aout_sys_t *p_sys;
-    audio_output_t *p_aout = (audio_output_t*)(p_this);
+    struct aout_sys_t *p_sys = aout->sys:
 
     int status, size;
     int afSampleRate, afFrameCount, afLatency, minBufCount, minFrameCount;
     int stream_type, channel, rate, format;
 
-    p_sys = (struct aout_sys_t*) malloc(sizeof(aout_sys_t));
-    if (!p_sys)
-        return VLC_ENOMEM;
-
-    p_sys->libmedia = InitLibrary(p_sys);
-    if (!p_sys->libmedia) {
-        msg_Err(p_aout, "Could not initialize libmedia.so!");
-        free(p_sys);
-        return VLC_EGENERIC;
-    }
-
     /* 4000 <= frequency <= 48000 */
-    rate = p_aout->format.i_rate;
+    rate = fmt->i_rate;
     if (rate < 4000)
         rate = 4000;
     if (rate > 48000)
@@ -204,22 +192,22 @@ static int Open(vlc_object_t *p_this)
     stream_type = MUSIC;
 
     /* We can only accept U8 and S16L */
-    if (p_aout->format.i_format != VLC_CODEC_U8 && p_aout->format.i_format != VLC_CODEC_S16L)
-        p_aout->format.i_format = VLC_CODEC_S16L;
-    format = (p_aout->format.i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT;
+    if (fmt->i_format != VLC_CODEC_U8 && fmt->i_format != VLC_CODEC_S16L)
+        fmt->i_format = VLC_CODEC_S16L;
+    format = (fmt->i_format == VLC_CODEC_S16L) ? PCM_16_BIT : PCM_8_BIT;
 
     /* TODO: android supports more channels */
-    p_aout->format.i_original_channels = p_aout->format.i_physical_channels;
-    switch(aout_FormatNbChannels(&p_aout->format))
+    fmt->i_original_channels = fmt->i_physical_channels;
+    switch(aout_FormatNbChannels(fmt))
     {
     case 1:
         channel = CHANNEL_OUT_MONO;
-        p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+        fmt->i_physical_channels = AOUT_CHAN_CENTER;
         break;
     case 2:
     default:
         channel = CHANNEL_OUT_STEREO;
-        p_aout->format.i_physical_channels = AOUT_CHANS_STEREO;
+        fmt->i_physical_channels = AOUT_CHANS_STEREO;
         break;
     }
 
@@ -230,8 +218,6 @@ static int Open(vlc_object_t *p_this)
         status ^= p_sys->as_getOutputLatency((uint32_t*)(&afLatency), stream_type);
         if (status != 0) {
             msg_Err(p_aout, "Could not query the AudioStream parameters");
-            dlclose(p_sys->libmedia);
-            free(p_sys);
             return VLC_EGENERIC;
         }
         minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
@@ -243,8 +229,6 @@ static int Open(vlc_object_t *p_this)
         status = p_sys->at_getMinFrameCount(&minFrameCount, stream_type, rate);
         if (status != 0) {
             msg_Err(p_aout, "Could not query the AudioTrack parameters");
-            dlclose(p_sys->libmedia);
-            free(p_sys);
             return VLC_EGENERIC;
         }
     }
@@ -253,11 +237,8 @@ static int Open(vlc_object_t *p_this)
 
     /* Sizeof(AudioTrack) == 0x58 (not sure) on 2.2.1, this should be enough */
     p_sys->AudioTrack = malloc(SIZE_OF_AUDIOTRACK);
-    if (!p_sys->AudioTrack) {
-        dlclose(p_sys->libmedia);
-        free(p_sys);
+    if (!p_sys->AudioTrack)
         return VLC_ENOMEM;
-    }
 
     *((uint32_t *) ((uint32_t)p_sys->AudioTrack + SIZE_OF_AUDIOTRACK - 4)) = 0xbaadbaad;
     // Higher than android 2.2
@@ -280,9 +261,7 @@ static int Open(vlc_object_t *p_this)
     }
     if (status != 0) {
         msg_Err(p_aout, "Cannot create AudioTrack!");
-        dlclose(p_sys->libmedia);
         free(p_sys->AudioTrack);
-        free(p_sys);
         return VLC_EGENERIC;
     }
 
@@ -292,7 +271,7 @@ static int Open(vlc_object_t *p_this)
 
     p_sys->at_start(p_sys->AudioTrack);
 
-    p_aout->format.i_rate = rate;
+    fmt->i_rate = rate;
 
     return VLC_SUCCESS;
 }
@@ -306,8 +285,6 @@ static void Close(vlc_object_t *p_this)
     p_sys->at_flush(p_sys->AudioTrack);
     p_sys->at_dtor(p_sys->AudioTrack);
     free(p_sys->AudioTrack);
-    dlclose(p_sys->libmedia);
-    free(p_sys);
 }
 
 /* FIXME: lipsync */
@@ -335,3 +312,34 @@ static void Pause(audio_output_t *p_aout, bool pause, mtime_t date)
         p_sys->at_start(p_sys->AudioTrack);
     }
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc(sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    sys->libmedia = InitLibrary(sys);
+    if (sys->libmedia == NULL) {
+        msg_Err(aout, "Could not initialize libmedia.so!");
+        free(sys);
+        return VLC_EGENERIC;
+    }
+
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    //aout_SoftVolumeInit(aout);
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    dlclose(sys->libmedia);
+    free(sys);
+}
index 5c8714154140c69dc753d99f39288dbb3c567596..49766cb3cd8f29cff743dad518ce29670b9d2768 100644 (file)
@@ -145,23 +145,17 @@ vlc_module_end ()
 /*****************************************************************************
  * Open: open macosx audio output
  *****************************************************************************/
-static int Open(vlc_object_t * p_this)
+static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
 {
     OSStatus                err = noErr;
     UInt32                  i_param_size = 0;
     struct aout_sys_t       *p_sys = NULL;
     vlc_value_t             val;
-    audio_output_t          *p_aout = (audio_output_t *)p_this;
 
     /* Use int here, to match kAudioDevicePropertyDeviceIsAlive
      * property size */
     int                     b_alive = false;
 
-    /* Allocate structure */
-    p_aout->sys = malloc(sizeof(aout_sys_t));
-    if (p_aout->sys == NULL)
-        return VLC_ENOMEM;
-
     p_sys = p_aout->sys;
     p_sys->i_default_dev = 0;
     p_sys->i_selected_dev = 0;
@@ -183,7 +177,7 @@ static int Open(vlc_object_t * p_this)
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
 
-    aout_FormatPrint(p_aout, "VLC is looking for:", &p_aout->format);
+    aout_FormatPrint(p_aout, "VLC is looking for:", fmt);
 
     /* Persistent device variable */
     if (var_Type(p_aout->p_libvlc, "macosx-audio-device") == 0)
@@ -255,7 +249,7 @@ static int Open(vlc_object_t * p_this)
     var_AddCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
 
     /* Check for Digital mode or Analog output mode */
-    if (AOUT_FMT_SPDIF (&p_aout->format) && b_supports_digital) {
+    if (AOUT_FMT_SPDIF (fmt) && b_supports_digital) {
         if (OpenSPDIF (p_aout)) {
             msg_Dbg(p_aout, "digital output successfully opened");
             return VLC_SUCCESS;
@@ -271,14 +265,13 @@ error:
     /* If we reach this, this aout has failed */
     msg_Err(p_aout, "opening the auhal output failed");
     var_Destroy(p_aout, "audio-device");
-    free(p_sys);
     return VLC_EGENERIC;
 }
 
 /*****************************************************************************
  * Open: open and setup a HAL AudioUnit to do analog (multichannel) audio output
  *****************************************************************************/
-static int OpenAnalog(audio_output_t *p_aout)
+static int OpenAnalog(audio_output_t *p_aout, audio_sample_format_t *fmt)
 {
     struct aout_sys_t           *p_sys = p_aout->sys;
     OSStatus                    err = noErr;
@@ -374,15 +367,15 @@ static int OpenAnalog(audio_output_t *p_aout)
         msg_Dbg(p_aout, "layout of AUHAL has %d channels" , (int)layout->mNumberChannelDescriptions);
 
         /* Initialize the VLC core channel count */
-        p_aout->format.i_physical_channels = 0;
-        i_original = p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK;
+        fmt->i_physical_channels = 0;
+        i_original = fmt->i_original_channels & AOUT_CHAN_PHYSMASK;
 
         if (i_original == AOUT_CHAN_CENTER || layout->mNumberChannelDescriptions < 2) {
             /* We only need Mono or cannot output more than 1 channel */
-            p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
         } else if (i_original == (AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT) || layout->mNumberChannelDescriptions < 3) {
             /* We only need Stereo or cannot output more than 2 channels */
-            p_aout->format.i_physical_channels = AOUT_CHAN_RIGHT | AOUT_CHAN_LEFT;
+            fmt->i_physical_channels = AOUT_CHANS_STEREO;
         } else {
             /* We want more than stereo and we can do that */
             for (unsigned int i = 0; i < layout->mNumberChannelDescriptions; i++) {
@@ -390,38 +383,38 @@ static int OpenAnalog(audio_output_t *p_aout)
 
                 switch(layout->mChannelDescriptions[i].mChannelLabel) {
                     case kAudioChannelLabel_Left:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_LEFT;
+                        fmt->i_physical_channels |= AOUT_CHAN_LEFT;
                         continue;
                     case kAudioChannelLabel_Right:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_RIGHT;
+                        fmt->i_physical_channels |= AOUT_CHAN_RIGHT;
                         continue;
                     case kAudioChannelLabel_Center:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_CENTER;
+                        fmt->i_physical_channels |= AOUT_CHAN_CENTER;
                         continue;
                     case kAudioChannelLabel_LFEScreen:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_LFE;
+                        fmt->i_physical_channels |= AOUT_CHAN_LFE;
                         continue;
                     case kAudioChannelLabel_LeftSurround:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_REARLEFT;
+                        fmt->i_physical_channels |= AOUT_CHAN_REARLEFT;
                         continue;
                     case kAudioChannelLabel_RightSurround:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_REARRIGHT;
+                        fmt->i_physical_channels |= AOUT_CHAN_REARRIGHT;
                         continue;
                     case kAudioChannelLabel_RearSurroundLeft:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
+                        fmt->i_physical_channels |= AOUT_CHAN_MIDDLELEFT;
                         continue;
                     case kAudioChannelLabel_RearSurroundRight:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
+                        fmt->i_physical_channels |= AOUT_CHAN_MIDDLERIGHT;
                         continue;
                     case kAudioChannelLabel_CenterSurround:
-                        p_aout->format.i_physical_channels |= AOUT_CHAN_REARCENTER;
+                        fmt->i_physical_channels |= AOUT_CHAN_REARCENTER;
                         continue;
                     default:
                         msg_Warn(p_aout, "unrecognized channel form provided by driver: %d", (int)layout->mChannelDescriptions[i].mChannelLabel);
                 }
             }
-            if (p_aout->format.i_physical_channels == 0) {
-                p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+            if (fmt->i_physical_channels == 0) {
+                fmt->i_physical_channels = AOUT_CHANS_STEREO;
                 msg_Err(p_aout, "You should configure your speaker layout with Audio Midi Setup Utility in /Applications/Utilities. Now using Stereo mode.");
                 dialog_Fatal(p_aout, _("Audio device is not configured"), "%s",
                                 _("You should configure your speaker layout with "
@@ -432,14 +425,14 @@ static int OpenAnalog(audio_output_t *p_aout)
         free(layout);
     } else {
         msg_Warn(p_aout, "this driver does not support kAudioDevicePropertyPreferredChannelLayout. BAD DRIVER AUTHOR !!!");
-        p_aout->format.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+        fmt->i_physical_channels = AOUT_CHANS_STEREO;
     }
 
-    msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(&p_aout->format));
-    msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(&p_aout->format));
+    msg_Dbg(p_aout, "selected %d physical channels for device output", aout_FormatNbChannels(fmt));
+    msg_Dbg(p_aout, "VLC will output: %s", aout_FormatPrintChannels(fmt));
 
     memset (&new_layout, 0, sizeof(new_layout));
-    switch(aout_FormatNbChannels(&p_aout->format)) {
+    switch(aout_FormatNbChannels(fmt)) {
         case 1:
             new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Mono;
             break;
@@ -447,27 +440,27 @@ static int OpenAnalog(audio_output_t *p_aout)
             new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
             break;
         case 3:
-            if (p_aout->format.i_physical_channels & AOUT_CHAN_CENTER)
+            if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_7; // L R C
-            else if (p_aout->format.i_physical_channels & AOUT_CHAN_LFE)
+            else if (fmt->i_physical_channels & AOUT_CHAN_LFE)
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_4; // L R LFE
             break;
         case 4:
-            if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
+            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_LFE))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_10; // L R C LFE
-            else if (p_aout->format.i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
+            else if (fmt->i_physical_channels & (AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R Ls Rs
-            else if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
+            else if (fmt->i_physical_channels & (AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_3; // L R C Cs
             break;
         case 5:
-            if (p_aout->format.i_physical_channels & (AOUT_CHAN_CENTER))
+            if (fmt->i_physical_channels & (AOUT_CHAN_CENTER))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_19; // L R Ls Rs C
-            else if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
+            else if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_18; // L R Ls Rs LFE
             break;
         case 6:
-            if (p_aout->format.i_physical_channels & (AOUT_CHAN_LFE))
+            if (fmt->i_physical_channels & (AOUT_CHAN_LFE))
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_DVD_20; // L R Ls Rs C LFE
             else
                 new_layout.mChannelLayoutTag = kAudioChannelLayoutTag_AudioUnit_6_0; // L R Ls Rs C Cs
@@ -483,14 +476,14 @@ static int OpenAnalog(audio_output_t *p_aout)
     }
 
     /* Set up the format to be used */
-    DeviceFormat.mSampleRate = p_aout->format.i_rate;
+    DeviceFormat.mSampleRate = fmt->i_rate;
     DeviceFormat.mFormatID = kAudioFormatLinearPCM;
 
     /* We use float 32. It's the best supported format by both VLC and Coreaudio */
-    p_aout->format.i_format = VLC_CODEC_FL32;
+    fmt->i_format = VLC_CODEC_FL32;
     DeviceFormat.mFormatFlags = kAudioFormatFlagsNativeFloatPacked;
     DeviceFormat.mBitsPerChannel = 32;
-    DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(&p_aout->format);
+    DeviceFormat.mChannelsPerFrame = aout_FormatNbChannels(fmt);
 
     /* Calculate framesizes and stuff */
     DeviceFormat.mFramesPerPacket = 1;
@@ -519,10 +512,8 @@ static int OpenAnalog(audio_output_t *p_aout)
     msg_Dbg(p_aout, STREAM_FORMAT_MSG("the actual set AU format is " , DeviceFormat));
 
     /* Do the last VLC aout setups */
-    aout_FormatPrepare(&p_aout->format);
-    aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE);
-    p_aout->volume_set = VolumeSet;
-    p_aout->mute_set = MuteSet;
+    aout_FormatPrepare(fmt);
+    aout_PacketInit(p_aout, &p_sys->packet, FRAMESIZE, fmt);
 
     /* set the IOproc callback */
     input.inputProc = (AURenderCallback) RenderCallbackAnalog;
@@ -562,7 +553,7 @@ static int OpenAnalog(audio_output_t *p_aout)
 /*****************************************************************************
  * Setup a encoded digital stream (SPDIF)
  *****************************************************************************/
-static int OpenSPDIF (audio_output_t * p_aout)
+static int OpenSPDIF (audio_output_t * p_aout, audio_sample_format_t *fmt)
 {
     struct aout_sys_t       *p_sys = p_aout->sys;
     OSStatus                err = noErr;
@@ -690,7 +681,7 @@ static int OpenSPDIF (audio_output_t * p_aout)
                    p_format_list[j].mFormat.mFormatID == 'iac3' ||
                    p_format_list[j].mFormat.mFormatID == kAudioFormat60958AC3 ||
                    p_format_list[j].mFormat.mFormatID == kAudioFormatAC3) {
-                    if (p_format_list[j].mFormat.mSampleRate == p_aout->format.i_rate) {
+                    if (p_format_list[j].mFormat.mSampleRate == fmt->i_rate) {
                         i_requested_rate_format = j;
                         break;
                     } else if (p_format_list[j].mFormat.mSampleRate == p_sys->sfmt_revert.mSampleRate)
@@ -728,16 +719,14 @@ static int OpenSPDIF (audio_output_t * p_aout)
 
     /* Set the format flags */
     if (p_sys->stream_format.mFormatFlags & kAudioFormatFlagIsBigEndian)
-        p_aout->format.i_format = VLC_CODEC_SPDIFB;
+        fmt->i_format = VLC_CODEC_SPDIFB;
     else
-        p_aout->format.i_format = VLC_CODEC_SPDIFL;
-    p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-    p_aout->format.i_frame_length = A52_FRAME_NB;
-    p_aout->format.i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
-    aout_FormatPrepare(&p_aout->format);
-    aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB);
-    p_aout->volume_set = NULL;
-    p_aout->mute_set = NULL;
+        fmt->i_format = VLC_CODEC_SPDIFL;
+    fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+    fmt->i_frame_length = A52_FRAME_NB;
+    fmt->i_rate = (unsigned int)p_sys->stream_format.mSampleRate;
+    aout_FormatPrepare(fmt);
+    aout_PacketInit(p_aout, &p_sys->packet, A52_FRAME_NB, fmt);
 
     /* Add IOProc callback */
     err = AudioDeviceCreateIOProcID(p_sys->i_selected_dev,
@@ -775,9 +764,8 @@ static int OpenSPDIF (audio_output_t * p_aout)
 /*****************************************************************************
  * Close: Close HAL AudioUnit
  *****************************************************************************/
-static void Close(vlc_object_t * p_this)
+static void Stop(audio_output_t *p_aout)
 {
-    audio_output_t     *p_aout = (audio_output_t *)p_this;
     struct aout_sys_t   *p_sys = p_aout->sys;
     OSStatus            err = noErr;
     UInt32              i_param_size = 0;
@@ -855,7 +843,6 @@ static void Close(vlc_object_t * p_this)
     var_DelCallback(p_aout, "audio-device", AudioDeviceCallback, NULL);
 
     aout_PacketDestroy(p_aout);
-    free(p_sys);
 }
 
 /*****************************************************************************
@@ -1215,8 +1202,8 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *_p_aout,
                     &p_sys->p_remainder_buffer[p_sys->i_read_bytes],
                     i_mData_bytes);
         p_sys->i_read_bytes += i_mData_bytes;
-        current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
-                        (i_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
+        current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
+                        (i_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
 
         if (p_sys->i_read_bytes >= p_sys->i_total_bytes)
             p_sys->i_read_bytes = p_sys->i_total_bytes = 0;
@@ -1245,8 +1232,8 @@ static OSStatus RenderCallbackAnalog(vlc_object_t *_p_aout,
                 break;
             } else
                 /* update current_date */
-                current_date += (mtime_t) ((mtime_t) 1000000 / p_aout->format.i_rate) *
-                                (i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_aout->format)); // 4 is fl32 specific
+                current_date += (mtime_t) ((mtime_t) 1000000 / p_sys->packet.format.i_rate) *
+                                (i_second_mData_bytes / 4 / aout_FormatNbChannels(&p_sys->packet.format)); // 4 is fl32 specific
             block_Release(p_buffer);
         } else {
             memset((uint8_t *)ioData->mBuffers[0].mData +i_mData_bytes,
@@ -1398,3 +1385,26 @@ static int MuteSet(audio_output_t * p_aout, bool mute)
 
     return 0;
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc(sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->volume_set = VolumeSet;
+    aout->mute_set = MuteSet;
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
+}
index e345ffc40835ae7df07544054668939393f58d1d..5887f989b3ba37ac873ff6fe4cd4c4c06bf2ee55 100644 (file)
@@ -39,8 +39,6 @@
 
 #include "windows_audio_common.h"
 
-#define FRAME_SIZE ((int)p_aout->format.i_rate/20) /* Size in samples */
-
 /*****************************************************************************
  * notification_thread_t: DirectX event thread
  *****************************************************************************/
@@ -98,14 +96,15 @@ struct aout_sys_t
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int  OpenAudio  ( vlc_object_t * );
-static void CloseAudio ( vlc_object_t * );
+static int  Open( vlc_object_t * );
+static void Close( vlc_object_t * );
+static void Stop( audio_output_t * );
 static void Play       ( audio_output_t *, block_t *, mtime_t * );
 static int  VolumeSet  ( audio_output_t *, float );
 static int  MuteSet    ( audio_output_t *, bool );
 
 /* local functions */
-static void Probe             ( audio_output_t * );
+static void Probe( audio_output_t *, const audio_sample_format_t * );
 static int  InitDirectSound   ( audio_output_t * );
 static int  CreateDSBuffer    ( audio_output_t *, int, int, int, int, int, bool );
 static int  CreateDSBufferPCM ( audio_output_t *, vlc_fourcc_t*, int, int, bool );
@@ -154,7 +153,7 @@ vlc_module_begin ()
                  VOLUME_TEXT, VOLUME_LONGTEXT, true )
         change_integer_range( DSBVOLUME_MIN, DSBVOLUME_MAX )
 
-    set_callbacks( OpenAudio, CloseAudio )
+    set_callbacks( Open, Close )
 vlc_module_end ()
 
 /*****************************************************************************
@@ -162,9 +161,8 @@ vlc_module_end ()
  *****************************************************************************
  * This function opens and setups Direct Sound.
  *****************************************************************************/
-static int OpenAudio( vlc_object_t *p_this )
+static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
-    audio_output_t * p_aout = (audio_output_t *)p_this;
     vlc_value_t val;
     char * psz_speaker;
     int i = 0;
@@ -173,11 +171,6 @@ static int OpenAudio( vlc_object_t *p_this )
 
     msg_Dbg( p_aout, "Opening DirectSound Audio Output" );
 
-   /* Allocate structure */
-    p_aout->sys = calloc( 1, sizeof( aout_sys_t ) );
-    if( unlikely( p_aout->sys == NULL ) )
-        return VLC_ENOMEM;
-
     /* Retrieve config values */
     var_Create( p_aout, "directx-audio-float32",
                 VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
@@ -210,7 +203,7 @@ static int OpenAudio( vlc_object_t *p_this )
 
     if( var_Type( p_aout, "audio-device" ) == 0 )
     {
-        Probe( p_aout );
+        Probe( p_aout, fmt );
     }
 
     if( var_Get( p_aout, "audio-device", &val ) < 0 )
@@ -222,17 +215,16 @@ static int OpenAudio( vlc_object_t *p_this )
     /* Open the device */
     if( val.i_int == AOUT_VAR_SPDIF )
     {
-        p_aout->format.i_format = VLC_CODEC_SPDIFL;
+        fmt->i_format = VLC_CODEC_SPDIFL;
 
         /* Calculate the frame size in bytes */
-        p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        p_aout->format.i_frame_length = A52_FRAME_NB;
-        p_aout->sys->i_frame_size = p_aout->format.i_bytes_per_frame;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
+        p_aout->sys->i_frame_size = fmt->i_bytes_per_frame;
 
         if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
-                            p_aout->format.i_physical_channels,
-                            aout_FormatNbChannels( &p_aout->format ),
-                            p_aout->format.i_rate,
+                            fmt->i_physical_channels,
+                            aout_FormatNbChannels( fmt ), fmt->i_rate,
                             p_aout->sys->i_frame_size, false )
             != VLC_SUCCESS )
         {
@@ -240,26 +232,27 @@ static int OpenAudio( vlc_object_t *p_this )
             goto error;
         }
 
-        aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
+        aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
     }
     else
     {
         if( val.i_int == AOUT_VAR_5_1 )
-            p_aout->format.i_physical_channels = AOUT_CHANS_5_0;
+            fmt->i_physical_channels = AOUT_CHANS_5_0;
         else if( val.i_int == AOUT_VAR_7_1 )
-            p_aout->format.i_physical_channels = AOUT_CHANS_7_1;
+            fmt->i_physical_channels = AOUT_CHANS_7_1;
         else if( val.i_int == AOUT_VAR_3F2R )
-            p_aout->format.i_physical_channels = AOUT_CHANS_5_0;
+            fmt->i_physical_channels = AOUT_CHANS_5_0;
         else if( val.i_int == AOUT_VAR_2F2R )
-            p_aout->format.i_physical_channels = AOUT_CHANS_4_0;
+            fmt->i_physical_channels = AOUT_CHANS_4_0;
         else if( val.i_int == AOUT_VAR_MONO )
-            p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
         else
-            p_aout->format.i_physical_channels = AOUT_CHANS_2_0;
+            fmt->i_physical_channels = AOUT_CHANS_2_0;
 
-        if( CreateDSBufferPCM( p_aout, &p_aout->format.i_format,
-                               p_aout->format.i_physical_channels,
-                               p_aout->format.i_rate, false )
+        aout_FormatPrepare( fmt );
+
+        if( CreateDSBufferPCM( p_aout, &fmt->i_format,
+                               fmt->i_physical_channels, fmt->i_rate, false )
             != VLC_SUCCESS )
         {
             msg_Err( p_aout, "cannot open directx audio device" );
@@ -267,8 +260,7 @@ static int OpenAudio( vlc_object_t *p_this )
         }
 
         /* Calculate the frame size in bytes */
-        aout_FormatPrepare( &p_aout->format );
-        aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
+        aout_PacketInit( p_aout, &p_aout->sys->packet, fmt->i_rate / 20, fmt );
     }
 
     p_aout->sys->volume.volume = -1;
@@ -315,14 +307,14 @@ static int OpenAudio( vlc_object_t *p_this )
     return VLC_SUCCESS;
 
  error:
-    CloseAudio( VLC_OBJECT(p_aout) );
+    Stop( p_aout );
     return VLC_EGENERIC;
 }
 
 /*****************************************************************************
  * Probe: probe the audio device for available formats and channels
  *****************************************************************************/
-static void Probe( audio_output_t * p_aout )
+static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
 {
     vlc_value_t val, text;
     vlc_fourcc_t i_format;
@@ -334,10 +326,10 @@ static void Probe( audio_output_t * p_aout )
     var_Change( p_aout, "audio-device", VLC_VAR_SETTEXT, &text, NULL );
 
     /* Test for 5.1 support */
-    if( p_aout->format.i_physical_channels == AOUT_CHANS_5_1 )
+    if( fmt->i_physical_channels == AOUT_CHANS_5_1 )
     {
         if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_5_1,
-                               p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                               fmt->i_rate, true ) == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_5_1;
             text.psz_string = (char*) "5.1";
@@ -350,10 +342,10 @@ static void Probe( audio_output_t * p_aout )
     }
 
     /* Test for 7.1 support */
-    if( p_aout->format.i_physical_channels == AOUT_CHANS_7_1 )
+    if( fmt->i_physical_channels == AOUT_CHANS_7_1 )
     {
         if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_7_1,
-                               p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                               fmt->i_rate, true ) == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_7_1;
             text.psz_string = (char*) "7.1";
@@ -366,10 +358,10 @@ static void Probe( audio_output_t * p_aout )
     }
 
     /* Test for 3 Front 2 Rear support */
-    if( p_aout->format.i_physical_channels == AOUT_CHANS_5_0 )
+    if( fmt->i_physical_channels == AOUT_CHANS_5_0 )
     {
         if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_5_0,
-                               p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                               fmt->i_rate, true ) == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_3F2R;
             text.psz_string = _("3 Front 2 Rear");
@@ -385,11 +377,10 @@ static void Probe( audio_output_t * p_aout )
     }
 
     /* Test for 2 Front 2 Rear support */
-    if( ( p_aout->format.i_physical_channels & AOUT_CHANS_4_0 )
-                                                            == AOUT_CHANS_4_0 )
+    if( ( fmt->i_physical_channels & AOUT_CHANS_4_0 ) == AOUT_CHANS_4_0 )
     {
         if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_4_0,
-                               p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                               fmt->i_rate, true ) == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_2F2R;
             text.psz_string = _("2 Front 2 Rear");
@@ -406,7 +397,7 @@ static void Probe( audio_output_t * p_aout )
 
     /* Test for stereo support */
     if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHANS_2_0,
-                           p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                           fmt->i_rate, true ) == VLC_SUCCESS )
     {
         val.i_int = AOUT_VAR_STEREO;
         text.psz_string = _("Stereo");
@@ -422,7 +413,7 @@ static void Probe( audio_output_t * p_aout )
 
     /* Test for mono support */
     if( CreateDSBufferPCM( p_aout, &i_format, AOUT_CHAN_CENTER,
-                           p_aout->format.i_rate, true ) == VLC_SUCCESS )
+                           fmt->i_rate, true ) == VLC_SUCCESS )
     {
         val.i_int = AOUT_VAR_MONO;
         text.psz_string = _("Mono");
@@ -503,12 +494,11 @@ static void Probe( audio_output_t * p_aout )
     var_Set( p_aout, "audio-device", val );
 
     /* Test for SPDIF support */
-    if ( AOUT_FMT_SPDIF( &p_aout->format ) )
+    if ( AOUT_FMT_SPDIF( fmt ) )
     {
         if( CreateDSBuffer( p_aout, VLC_CODEC_SPDIFL,
-                            p_aout->format.i_physical_channels,
-                            aout_FormatNbChannels( &p_aout->format ),
-                            p_aout->format.i_rate,
+                            fmt->i_physical_channels,
+                            aout_FormatNbChannels( fmt ), fmt->i_rate,
                             AOUT_SPDIF_SIZE, true )
             == VLC_SUCCESS )
         {
@@ -603,9 +593,8 @@ static int MuteSet( audio_output_t *p_aout, bool mute )
 /*****************************************************************************
  * CloseAudio: close the audio device
  *****************************************************************************/
-static void CloseAudio( vlc_object_t *p_this )
+static void Stop( audio_output_t *p_aout )
 {
-    audio_output_t * p_aout = (audio_output_t *)p_this;
     aout_sys_t *p_sys = p_aout->sys;
 
     msg_Dbg( p_aout, "closing audio device" );
@@ -629,11 +618,7 @@ static void CloseAudio( vlc_object_t *p_this )
     /* finally release the DirectSound object */
     if( p_sys->p_dsobject ) IDirectSound_Release( p_sys->p_dsobject );
 
-    /* free DSOUND.DLL */
-    if( p_sys->hdsound_dll ) FreeLibrary( p_sys->hdsound_dll );
-
     free( p_aout->sys->p_device_guid );
-    free( p_sys );
 }
 
 /*****************************************************************************
@@ -681,13 +666,6 @@ static int InitDirectSound( audio_output_t *p_aout )
     HRESULT (WINAPI *OurDirectSoundCreate)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
     HRESULT (WINAPI *OurDirectSoundEnumerate)(LPDSENUMCALLBACKW, LPVOID);
 
-    p_aout->sys->hdsound_dll = LoadLibrary("DSOUND.DLL");
-    if( p_aout->sys->hdsound_dll == NULL )
-    {
-        msg_Warn( p_aout, "cannot open DSOUND.DLL" );
-        goto error;
-    }
-
     OurDirectSoundCreate = (void *)
         GetProcAddress( p_aout->sys->hdsound_dll,
                         "DirectSoundCreate" );
@@ -742,11 +720,6 @@ static int InitDirectSound( audio_output_t *p_aout )
 
  error:
     p_aout->sys->p_dsobject = NULL;
-    if( p_aout->sys->hdsound_dll )
-    {
-        FreeLibrary( p_aout->sys->hdsound_dll );
-        p_aout->sys->hdsound_dll = NULL;
-    }
     return VLC_EGENERIC;
 
 }
@@ -903,12 +876,12 @@ static int CreateDSBufferPCM( audio_output_t *p_aout, vlc_fourcc_t *i_format,
         i_nb_channels > 2 ||
         CreateDSBuffer( p_aout, VLC_CODEC_FL32,
                         i_channels, i_nb_channels, i_rate,
-                        FRAME_SIZE * 4 * i_nb_channels, b_probe )
+                        (i_rate / 20) * 4 * i_nb_channels, b_probe )
         != VLC_SUCCESS )
     {
         if ( CreateDSBuffer( p_aout, VLC_CODEC_S16L,
                              i_channels, i_nb_channels, i_rate,
-                             FRAME_SIZE * 2 * i_nb_channels, b_probe )
+                             (i_rate / 20) * 2 * i_nb_channels, b_probe )
              != VLC_SUCCESS )
         {
             return VLC_EGENERIC;
@@ -1079,15 +1052,15 @@ static void* DirectSoundThread( void *data )
 
         /* Detect underruns */
         if( l_queued && mtime - last_time >
-            INT64_C(1000000) * l_queued / p_aout->format.i_rate )
+            INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate )
         {
             msg_Dbg( p_aout, "detected underrun!" );
         }
         last_time = mtime;
 
         /* Try to fill in as many frame buffers as possible */
-        l_read /= (p_aout->format.i_bytes_per_frame /
-            p_aout->format.i_frame_length);
+        l_read /= (p_aout->sys->packet.format.i_bytes_per_frame /
+            p_aout->sys->packet.format.i_frame_length);
         l_queued = p_notif->i_write_slot * i_frame_siz - l_read;
         if( l_queued < 0 ) l_queued += (i_frame_siz * FRAMES_NUM);
         l_free_slots = (FRAMES_NUM * i_frame_siz - l_queued) / i_frame_siz;
@@ -1096,7 +1069,7 @@ static void* DirectSoundThread( void *data )
         {
             block_t *p_buffer = aout_PacketNext( p_aout,
                 mtime + INT64_C(1000000) * (i * i_frame_siz + l_queued) /
-                p_aout->format.i_rate );
+                p_aout->sys->packet.format.i_rate );
 
             /* If there is no audio data available and we have some buffered
              * already, then just wait for the next time */
@@ -1108,7 +1081,7 @@ static void* DirectSoundThread( void *data )
 
         /* Sleep a reasonable amount of time */
         l_queued += (i * i_frame_siz);
-        msleep( INT64_C(1000000) * l_queued / p_aout->format.i_rate / 2 );
+        msleep( INT64_C(1000000) * l_queued / p_aout->sys->packet.format.i_rate / 2 );
     }
 
     /* make sure the buffer isn't playing */
@@ -1182,3 +1155,34 @@ error:
     return nb_devices;
 }
 
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = calloc(1, sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    sys->hdsound_dll = LoadLibrary(_T("DSOUND.DLL"));
+    if (sys->hdsound_dll == NULL)
+    {
+        msg_Warn(aout, "cannot open DSOUND.DLL");
+        free(sys);
+        return VLC_EGENERIC;
+    }
+
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->volume_set = NULL; /* FIXME */
+    aout->mute_set = NULL;
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    FreeLibrary(sys->hdsound_dll); /* free DSOUND.DLL */
+    free(sys);
+}
index 7f498c0ea96cc8a5b24a2292d4bf451565f14a04..0622843829b9d676101cc3686fdc7d99b6a1fa96 100644 (file)
@@ -71,7 +71,6 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
  * Local prototypes.
  *****************************************************************************/
 static int     Open        ( vlc_object_t * );
-static void    Close       ( vlc_object_t * );
 static void    Play        ( audio_output_t *, block_t *, mtime_t * );
 
 /*****************************************************************************
@@ -121,21 +120,17 @@ vlc_module_begin ()
 
     set_capability( "audio output", 0 )
     add_shortcut( "file", "audiofile" )
-    set_callbacks( Open, Close )
+    set_callbacks( Open, NULL )
 vlc_module_end ()
 
-/*****************************************************************************
- * Open: open a dummy audio device
- *****************************************************************************/
-static int Open( vlc_object_t * p_this )
+static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
-    audio_output_t * p_aout = (audio_output_t *)p_this;
     char * psz_name, * psz_format;
     const char * const * ppsz_compare = format_list;
     int i_channels, i = 0;
 
-    psz_name = var_CreateGetString( p_this, "audiofile-file" );
-    if( !psz_name || !*psz_name )
+    psz_name = var_InheritString( p_aout, "audiofile-file" );
+    if( !psz_name )
     {
         msg_Err( p_aout, "you need to specify an output file name" );
         free( psz_name );
@@ -164,7 +159,8 @@ static int Open( vlc_object_t * p_this )
     p_aout->flush = NULL;
 
     /* Audio format */
-    psz_format = var_CreateGetString( p_this, "audiofile-format" );
+    psz_format = var_InheritString( p_aout, "audiofile-format" );
+    if ( !psz_format ) abort(); /* FIXME */
 
     while ( *ppsz_compare != NULL )
     {
@@ -187,28 +183,22 @@ static int Open( vlc_object_t * p_this )
     }
     free( psz_format );
 
-    p_aout->format.i_format = format_int[i];
-    if ( AOUT_FMT_SPDIF( &p_aout->format ) )
+    fmt->i_format = format_int[i];
+    if ( AOUT_FMT_SPDIF( fmt ) )
     {
-        p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        p_aout->format.i_frame_length = A52_FRAME_NB;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
     }
-    p_aout->volume_set = NULL;
-    p_aout->mute_set = NULL;
 
     /* Channels number */
-    i_channels = var_CreateGetInteger( p_this, "audiofile-channels" );
-
+    i_channels = var_InheritInteger( p_aout, "audiofile-channels" );
     if( i_channels > 0 && i_channels <= CHANNELS_MAX )
     {
-        p_aout->format.i_physical_channels =
-            pi_channels_maps[i_channels];
+        fmt->i_physical_channels = pi_channels_maps[i_channels];
     }
 
     /* WAV header */
-    p_aout->sys->b_add_wav_header = var_CreateGetBool( p_this,
-                                                        "audiofile-wav" );
-
+    p_aout->sys->b_add_wav_header = var_InheritBool( p_aout, "audiofile-wav" );
     if( p_aout->sys->b_add_wav_header )
     {
         /* Write wave header */
@@ -216,7 +206,7 @@ static int Open( vlc_object_t * p_this )
 
         memset( wh, 0, sizeof(*wh) );
 
-        switch( p_aout->format.i_format )
+        switch( fmt->i_format )
         {
         case VLC_CODEC_FL32:
             wh->Format     = WAVE_FORMAT_IEEE_FLOAT;
@@ -239,8 +229,8 @@ static int Open( vlc_object_t * p_this )
         wh->SubChunkID = VLC_FOURCC('f', 'm', 't', ' ');
         wh->SubChunkLength = 16;
 
-        wh->Modus = aout_FormatNbChannels( &p_aout->format );
-        wh->SampleFreq = p_aout->format.i_rate;
+        wh->Modus = aout_FormatNbChannels( fmt );
+        wh->SampleFreq = fmt->i_rate;
         wh->BytesPerSample = wh->Modus * ( wh->BitsPerSample / 8 );
         wh->BytesPerSec = wh->BytesPerSample * wh->SampleFreq;
 
@@ -269,10 +259,8 @@ static int Open( vlc_object_t * p_this )
 /*****************************************************************************
  * Close: close our file
  *****************************************************************************/
-static void Close( vlc_object_t * p_this )
+static void Stop( audio_output_t *p_aout )
 {
-    audio_output_t * p_aout = (audio_output_t *)p_this;
-
     msg_Dbg( p_aout, "closing audio file" );
 
     if( p_aout->sys->b_add_wav_header )
@@ -326,3 +314,14 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer,
     block_Release( p_buffer );
     (void) drift;
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->volume_set = NULL;
+    aout->mute_set = NULL;
+    return VLC_SUCCESS;
+}
index 6a944eba0a71796c3a90d2685f28a40d66b34614..4b641a17e409a5ba0e6d09e7eaea5eb4ed07c717 100644 (file)
@@ -99,26 +99,15 @@ vlc_module_begin ()
     set_callbacks( Open, Close )
 vlc_module_end ()
 
-/*****************************************************************************
- * Open: create a JACK client
- *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+
+static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
     char psz_name[32];
-    audio_output_t *p_aout = (audio_output_t *)p_this;
-    struct aout_sys_t *p_sys = NULL;
+    struct aout_sys_t *p_sys = p_aout->sys;
     int status = VLC_SUCCESS;
     unsigned int i;
     int i_error;
 
-    /* Allocate structure */
-    p_sys = calloc( 1, sizeof( aout_sys_t ) );
-    if( p_sys == NULL )
-    {
-        status = VLC_ENOMEM;
-        goto error_out;
-    }
-    p_aout->sys = p_sys;
     p_sys->latency = 0;
 
     /* Connect to the JACK server */
@@ -139,18 +128,18 @@ static int Open( vlc_object_t *p_this )
     jack_set_graph_order_callback ( p_sys->p_jack_client, GraphChange, p_aout );
 
     /* JACK only supports fl32 format */
-    p_aout->format.i_format = VLC_CODEC_FL32;
+    fmt->i_format = VLC_CODEC_FL32;
     // TODO add buffer size callback
-    p_aout->format.i_rate = jack_get_sample_rate( p_sys->p_jack_client );
+    fmt->i_rate = jack_get_sample_rate( p_sys->p_jack_client );
 
     p_aout->play = aout_PacketPlay;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
     aout_PacketInit( p_aout, &p_sys->packet,
-                     jack_get_buffer_size( p_sys->p_jack_client ) );
+                     jack_get_buffer_size( p_sys->p_jack_client ), fmt );
     aout_SoftVolumeInit( p_aout );
 
-    p_sys->i_channels = aout_FormatNbChannels( &p_aout->format );
+    p_sys->i_channels = aout_FormatNbChannels( fmt );
 
     p_sys->p_jack_ports = malloc( p_sys->i_channels *
                                   sizeof(jack_port_t *) );
@@ -231,7 +220,7 @@ static int Open( vlc_object_t *p_this )
     }
 
     msg_Dbg( p_aout, "JACK audio output initialized (%d channels, rate=%d)",
-             p_sys->i_channels, p_aout->format.i_rate );
+             p_sys->i_channels, fmt->i_rate );
 
 error_out:
     /* Clean up, if an error occurred */
@@ -245,7 +234,6 @@ error_out:
         }
         free( p_sys->p_jack_ports );
         free( p_sys->p_jack_buffers );
-        free( p_sys );
     }
     return status;
 }
@@ -338,10 +326,9 @@ static int GraphChange( void *p_arg )
 /*****************************************************************************
  * Close: close the JACK client
  *****************************************************************************/
-static void Close( vlc_object_t *p_this )
+static void Stop( audio_output_t *p_aout )
 {
     int i_error;
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     struct aout_sys_t *p_sys = p_aout->sys;
 
     i_error = jack_deactivate( p_sys->p_jack_client );
@@ -358,5 +345,26 @@ static void Close( vlc_object_t *p_this )
     free( p_sys->p_jack_ports );
     free( p_sys->p_jack_buffers );
     aout_PacketDestroy( p_aout );
-    free( p_sys );
+}
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = calloc(1, sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout_SoftVolumeInit(aout);
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
 }
index afca932bb239ebd021d7db08195ff185b432ebfa..3cac90a1fba17399ea4807d3c64b5c386aad86f4 100644 (file)
@@ -55,7 +55,6 @@ struct aout_sys_t
  * Local prototypes
  *****************************************************************************/
 static int  Open  ( vlc_object_t * );
-static void Close ( vlc_object_t * );
 static void Play  ( audio_output_t *_p_aout, block_t *block, mtime_t * );
 
 static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
@@ -94,15 +93,14 @@ vlc_module_begin ()
     add_bool( "kai-audio-exclusive-mode", false,
               KAI_AUDIO_EXCLUSIVE_MODE_TEXT, KAI_AUDIO_EXCLUSIVE_MODE_LONGTEXT,
               true )
-    set_callbacks( Open, Close )
+    set_callbacks( Open, NULL )
 vlc_module_end ()
 
 /*****************************************************************************
  * Open: open the audio device
  *****************************************************************************/
-static int Open ( vlc_object_t *p_this )
+static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     aout_sys_t *p_sys;
     char *psz_mode;
     ULONG i_kai_mode;
@@ -110,7 +108,7 @@ static int Open ( vlc_object_t *p_this )
     int i_nb_channels;
     int i_bytes_per_frame;
     vlc_value_t val, text;
-    audio_format_t format =  p_aout->format;
+    audio_format_t format =  *format;
 
     /* Allocate structure */
     p_aout->sys = calloc( 1, sizeof( aout_sys_t ) );
@@ -201,7 +199,7 @@ static int Open ( vlc_object_t *p_this )
     msg_Dbg( p_aout, "obtained i_bytes_per_frame = %d",
              format.i_bytes_per_frame );
 
-    p_aout->format   = format;
+    *fmt = format;
 
     p_aout->play  = Play;
     p_aout->pause = aout_PacketPause;
@@ -267,9 +265,8 @@ static void Play (audio_output_t *p_aout, block_t *block,
 /*****************************************************************************
  * Close: close the audio device
  *****************************************************************************/
-static void Close ( vlc_object_t *p_this )
+static void Stop ( audio_output_t *p_aout )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     aout_sys_t *p_sys = p_aout->sys;
 
     kaiClose( p_sys->hkai );
@@ -341,3 +338,13 @@ static ULONG APIENTRY KaiCallback( PVOID p_cb_data,
 
     return i_buf_size;
 }
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+
+    /* FIXME: set volume/mute here */
+    aout->start = Start;
+    aout->stop = Stop;
+    return VLC_SUCCESS;
+}
index 8a0182b88e69cde0727a518c7cdeddc843e2ce01..fbde13d2bf052d7edf2940e4c79e7d6e2f2511b9 100644 (file)
@@ -82,7 +82,6 @@ struct aout_sys_t
  * Local prototypes.
  *****************************************************************************/
 static int  Open        ( vlc_object_t * );
-static void Close       ( vlc_object_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -96,7 +95,7 @@ vlc_module_begin ()
 
     set_capability( "audio output", 170 )
     add_shortcut( "opensles", "android" )
-    set_callbacks( Open, Close )
+    set_callbacks( Open, NULL )
 vlc_module_end ()
 
 
@@ -235,9 +234,8 @@ static void PlayedCallback (SLAndroidSimpleBufferQueueItf caller, void *pContext
 /*****************************************************************************
  * Open
  *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     SLresult       result;
     SLEngineItf    engineEngine;
 
@@ -321,7 +319,7 @@ static int Open( vlc_object_t *p_this )
     SLDataFormat_PCM format_pcm;
     format_pcm.formatType       = SL_DATAFORMAT_PCM;
     format_pcm.numChannels      = 2;
-    format_pcm.samplesPerSec    = ((SLuint32) p_aout->format.i_rate * 1000) ;
+    format_pcm.samplesPerSec    = ((SLuint32) fmt->i_rate * 1000) ;
     format_pcm.bitsPerSample    = SL_PCMSAMPLEFORMAT_FIXED_16;
     format_pcm.containerSize    = SL_PCMSAMPLEFORMAT_FIXED_16;
     format_pcm.channelMask      = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT;
@@ -368,13 +366,13 @@ static int Open( vlc_object_t *p_this )
     p_sys->pp_last = &p_sys->p_chain;
 
     // we want 16bit signed data little endian.
-    p_aout->format.i_format              = VLC_CODEC_S16L;
-    p_aout->format.i_physical_channels   = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
-    p_aout->play                         = Play;
-    p_aout->pause                        = Pause;
-    p_aout->flush                        = Flush;
+    fmt->i_format              = VLC_CODEC_S16L;
+    fmt->i_physical_channels   = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+    p_aout->play               = Play;
+    p_aout->pause              = Pause;
+    p_aout->flush               = Flush;
 
-    aout_FormatPrepare( &p_aout->format );
+    aout_FormatPrepare( fmt );
 
     return VLC_SUCCESS;
 error:
@@ -385,9 +383,8 @@ error:
 /*****************************************************************************
  * Close
  *****************************************************************************/
-static void Close( vlc_object_t *p_this )
+static void Stop( audio_output_t *p_aout )
 {
-    audio_output_t *p_aout = (audio_output_t*)p_this;
     aout_sys_t     *p_sys = p_aout->sys;
 
     SetPlayState( p_sys->playerPlay, SL_PLAYSTATE_STOPPED );
@@ -397,3 +394,13 @@ static void Close( vlc_object_t *p_this )
     vlc_mutex_destroy( &p_sys->lock );
     Clean( p_sys );
 }
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+
+    /* FIXME: set volume/mute here */
+    aout->start = Start;
+    aout->stop = Stop;
+    return VLC_SUCCESS;
+}
index 6d5bd62735902aab4a172dd5cd6502461a504ff4..9aee1b2ea9f9509d5605af7d3b0e07d64321a0b8 100644 (file)
@@ -59,7 +59,6 @@ struct aout_sys_t
 };
 
 static int Open (vlc_object_t *);
-static void Close (vlc_object_t *);
 
 #define AUDIO_DEV_TEXT N_("Audio output device")
 #define AUDIO_DEV_LONGTEXT N_("OSS device node path.")
@@ -72,7 +71,7 @@ vlc_module_begin ()
     add_string ("oss-audio-device", "",
                 AUDIO_DEV_TEXT, AUDIO_DEV_LONGTEXT, false)
     set_capability( "audio output", 100 )
-    set_callbacks( Open, Close )
+    set_callbacks (Open, NULL)
 vlc_module_end ()
 
 static void Play (audio_output_t *, block_t *, mtime_t *);
@@ -93,7 +92,7 @@ static int DeviceChanged (vlc_object_t *obj, const char *varname,
     return VLC_SUCCESS;
 }
 
-static int Open (vlc_object_t *obj)
+static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
     audio_output_t *aout = (audio_output_t *)obj;
 
@@ -124,10 +123,9 @@ static int Open (vlc_object_t *obj)
 
     /* Select audio format */
     int format;
-    vlc_fourcc_t fourcc = aout->format.i_format;
     bool spdif = false;
 
-    switch (fourcc)
+    switch (fmt->i_format)
     {
 #ifdef AFMT_FLOAT
         case VLC_CODEC_F64B:
@@ -154,7 +152,7 @@ static int Open (vlc_object_t *obj)
             format = AFMT_U8;
             break;
         default:
-            if (AOUT_FMT_SPDIF(&aout->format))
+            if (AOUT_FMT_SPDIF(fmt))
                 spdif = var_InheritBool (aout, "spdif");
             if (spdif)
                 format = AFMT_AC3;
@@ -174,21 +172,21 @@ static int Open (vlc_object_t *obj)
 
     switch (format)
     {
-        case AFMT_S8:     fourcc = VLC_CODEC_S8;   break;
-        case AFMT_U8:     fourcc = VLC_CODEC_U8;   break;
-        case AFMT_S16_BE: fourcc = VLC_CODEC_S16B; break;
-        case AFMT_S16_LE: fourcc = VLC_CODEC_S16L; break;
+        case AFMT_S8:     fmt->i_format = VLC_CODEC_S8;   break;
+        case AFMT_U8:     fmt->i_format = VLC_CODEC_U8;   break;
+        case AFMT_S16_BE: fmt->i_format = VLC_CODEC_S16B; break;
+        case AFMT_S16_LE: fmt->i_format = VLC_CODEC_S16L; break;
         //case AFMT_S24_BE:
         //case AFMT_S24_LE:
-        case AFMT_S32_BE: fourcc = VLC_CODEC_S32B; break;
-        case AFMT_S32_LE: fourcc = VLC_CODEC_S32L; break;
+        case AFMT_S32_BE: fmt->i_format = VLC_CODEC_S32B; break;
+        case AFMT_S32_LE: fmt->i_format = VLC_CODEC_S32L; break;
 #ifdef AFMT_FLOAT
-        case AFMT_FLOAT:  fourcc = VLC_CODEC_FL32; break;
+        case AFMT_FLOAT:  fmt->i_format = VLC_CODEC_FL32; break;
 #endif
         case AFMT_AC3:
             if (spdif)
             {
-                fourcc = VLC_CODEC_SPDIFL;
+                fmt->i_format = VLC_CODEC_SPDIFL;
                 break;
             }
         default:
@@ -197,7 +195,7 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Select channels count */
-    int channels = spdif ? 2 : aout_FormatNbChannels (&aout->format);
+    int channels = spdif ? 2 : aout_FormatNbChannels (fmt);
     if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) < 0)
     {
         msg_Err (aout, "cannot set %d channels: %m", channels);
@@ -217,7 +215,7 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Select sample rate */
-    int rate = spdif ? 48000 : aout->format.i_rate;
+    int rate = spdif ? 48000 : fmt->i_rate;
     if (ioctl (fd, SNDCTL_DSP_SPEED, &rate) < 0)
     {
         msg_Err (aout, "cannot set %d Hz sample rate: %m", rate);
@@ -225,7 +223,6 @@ static int Open (vlc_object_t *obj)
     }
 
     /* Setup audio_output_t */
-    aout->format.i_format = fourcc;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
@@ -234,14 +231,14 @@ static int Open (vlc_object_t *obj)
 
     if (spdif)
     {
-        aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        aout->format.i_frame_length = A52_FRAME_NB;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
     }
     else
     {
-        aout->format.i_rate = rate;
-        aout->format.i_original_channels =
-        aout->format.i_physical_channels = channels;
+        fmt->i_rate = rate;
+        fmt->i_original_channels =
+        fmt->i_physical_channels = channels;
 
         sys->level = 100;
         sys->mute = false;
@@ -303,9 +300,8 @@ error:
 /**
  * Releases the audio output.
  */
-static void Close (vlc_object_t *obj)
+static void Stop (audio_output_t *aout)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
     int fd = sys->fd;
 
@@ -445,3 +441,13 @@ static int MuteSet (audio_output_t *aout, bool mute)
     aout_MuteReport (aout, mute);
     return 0;
 }
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+
+    /* FIXME: set volume/mute here */
+    aout->start = Start;
+    aout->stop = Stop;
+    return VLC_SUCCESS;
+}
index deb493eda1ee1610018df519f5083e26a415a7aa..9bfa6fe147b4d79d7397a5560cacb09441715ca4 100644 (file)
@@ -134,13 +134,15 @@ static inline aout_packet_t *aout_packet (audio_output_t *aout)
     return (aout_packet_t *)(aout->sys);
 }
 
-void aout_PacketInit (audio_output_t *aout, aout_packet_t *p, unsigned samples)
+void aout_PacketInit (audio_output_t *aout, aout_packet_t *p, unsigned samples,
+                      const audio_sample_format_t *fmt)
 {
     assert (p == aout_packet (aout));
 
     vlc_mutex_init (&p->lock);
-    aout_FifoInit (&p->partial, aout->format.i_rate);
-    aout_FifoInit (&p->fifo, aout->format.i_rate);
+    p->format = *fmt;
+    aout_FifoInit (&p->partial, p->format.i_rate);
+    aout_FifoInit (&p->fifo, p->format.i_rate);
     p->pause_date = VLC_TS_INVALID;
     p->time_report = INT64_MIN;
     p->samples = samples;
@@ -253,9 +255,9 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
         available += p_buffer->i_nb_samples;
     }
 
-    if( AOUT_FMT_LINEAR( &p_aout->format ) )
+    if( AOUT_FMT_LINEAR( &p->format ) )
     {
-        const unsigned framesize = p_aout->format.i_bytes_per_frame;
+        const unsigned framesize = p->format.i_bytes_per_frame;
         /* Build packet with adequate number of samples */
         unsigned needed = samples * framesize;
 
@@ -285,7 +287,7 @@ static block_t *aout_OutputSlice (audio_output_t *p_aout)
                 needed /= framesize;
                 p_fifo->p_first->i_nb_samples -= needed;
 
-                mtime_t t = needed * CLOCK_FREQ / p_aout->format.i_rate;
+                mtime_t t = needed * CLOCK_FREQ / p->format.i_rate;
                 p_fifo->p_first->i_pts += t;
                 p_fifo->p_first->i_length -= t;
                 break;
@@ -322,7 +324,7 @@ block_t *aout_PacketNext (audio_output_t *p_aout, mtime_t start_date)
     aout_packet_t *p = aout_packet (p_aout);
     aout_fifo_t *p_fifo = &p->fifo;
     block_t *p_buffer;
-    const bool b_can_sleek = !AOUT_FMT_LINEAR(&p_aout->format);
+    const bool b_can_sleek = !AOUT_FMT_LINEAR(&p->format);
     const mtime_t now = mdate ();
     const mtime_t threshold =
         (b_can_sleek ? start_date : now) - AOUT_MAX_PTS_DELAY;
index cbedd4b384ee61683773813d9b6f337caa1f574b..e3dec5e8d15b91dca29baf740a95be24a1e2bc63 100644 (file)
@@ -68,7 +68,8 @@ struct aout_sys_t
     mtime_t last_pts; /**< Play time of buffer write offset */
     mtime_t paused; /**< Time when (last) paused */
     mtime_t desync; /**< Measured desynchronization */
-    unsigned rate; /**< Current stream sample rate */
+    unsigned nominal_rate; /**< Nominal stream sample rate */
+    unsigned actual_rate; /**< Current stream sample rate */
 };
 
 static void sink_list_cb(pa_context *, const pa_sink_info *, int, void *);
@@ -180,7 +181,7 @@ static void sink_info_cb(pa_context *c, const pa_sink_info *i, int eol,
 static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
 {
     aout_sys_t *sys = aout->sys;
-    const unsigned rate = aout->format.i_rate;
+    const unsigned rate = sys->nominal_rate;
 
     sys->first_pts = VLC_TS_INVALID;
     sys->last_pts = VLC_TS_INVALID;
@@ -189,7 +190,7 @@ static void stream_reset_sync(pa_stream *s, audio_output_t *aout)
     if (unlikely(op == NULL))
         return;
     pa_operation_unref(op);
-    sys->rate = rate;
+    sys->actual_rate = rate;
 }
 
 static void stream_start_now(pa_stream *s, audio_output_t *aout)
@@ -302,8 +303,8 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
     //msg_Dbg(aout, "desync: %+"PRId64" us (variation: %+"PRId64" us)",
     //        delta, change);
 
-    const unsigned inrate = aout->format.i_rate;
-    unsigned outrate = sys->rate;
+    const unsigned inrate = sys->nominal_rate;
+    unsigned outrate = sys->actual_rate;
     bool sync = false;
 
     if (delta < -AOUT_MAX_PTS_DELAY)
@@ -325,7 +326,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
     int limit = inrate >> 10;
     /* However, to improve stability and try to converge, closing to the
      * nominal rate is favored over drifting from it. */
-    if ((adj > 0) == (sys->rate > inrate))
+    if ((adj > 0) == (sys->actual_rate > inrate))
         limit *= 2;
     if (adj > +limit)
         adj = +limit;
@@ -342,7 +343,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
         outrate = inrate - limit;
 
     /* Apply adjusted sample rate */
-    if (outrate == sys->rate)
+    if (outrate == sys->actual_rate)
         return;
     pa_operation *op = pa_stream_update_sample_rate(s, outrate, NULL, NULL);
     if (unlikely(op == NULL)) {
@@ -351,7 +352,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
     }
     pa_operation_unref(op);
     msg_Dbg(aout, "changed sample rate to %u Hz",outrate);
-    sys->rate = outrate;
+    sys->actual_rate = outrate;
 }
 
 
@@ -699,36 +700,31 @@ static int StreamMove(vlc_object_t *obj, const char *varname, vlc_value_t old,
     return (op != NULL) ? VLC_SUCCESS : VLC_EGENERIC;
 }
 
+static void Stop(audio_output_t *);
 
 /**
  * Create a PulseAudio playback stream, a.k.a. a sink input.
  */
-static int Open(vlc_object_t *obj)
+static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-#if !PA_CHECK_VERSION(0,9,22)
-    if (!vlc_xlib_init(obj))
-        return VLC_EGENERIC;
-#endif
-
-    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
     pa_operation *op;
 
     /* Sample format specification */
     struct pa_sample_spec ss;
-    vlc_fourcc_t format = aout->format.i_format;
 #if PA_CHECK_VERSION(1,0,0)
     pa_encoding_t encoding = PA_ENCODING_INVALID;
 #endif
 
-    switch(format)
+    switch (fmt->i_format)
     {
         case VLC_CODEC_F64B:
-            format = VLC_CODEC_F32B;
+            fmt->i_format = VLC_CODEC_F32B;
         case VLC_CODEC_F32B:
             ss.format = PA_SAMPLE_FLOAT32BE;
             break;
         case VLC_CODEC_F64L:
-            format = VLC_CODEC_F32L;
+            fmt->i_format = VLC_CODEC_F32L;
         case VLC_CODEC_F32L:
             ss.format = PA_SAMPLE_FLOAT32LE;
             break;
@@ -751,28 +747,28 @@ static int Open(vlc_object_t *obj)
             ss.format = PA_SAMPLE_S16LE;
             break;
         case VLC_CODEC_S8:
-            format = VLC_CODEC_U8;
+            fmt->i_format = VLC_CODEC_U8;
         case VLC_CODEC_U8:
             ss.format = PA_SAMPLE_U8;
             break;
 #if PA_CHECK_VERSION(1,0,0)
         case VLC_CODEC_A52:
-            format = VLC_CODEC_SPDIFL;
+            fmt->i_format = VLC_CODEC_SPDIFL;
             encoding = PA_ENCODING_AC3_IEC61937;
             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
             break;
         /*case VLC_CODEC_EAC3:
-            format = VLC_CODEC_SPDIFL FIXME;
+            fmt->i_format = VLC_CODEC_SPDIFL FIXME;
             encoding = PA_ENCODING_EAC3_IEC61937;
             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
             break;
         case VLC_CODEC_MPGA:
-            format = VLC_CODEC_SPDIFL FIXME;
+            fmt->i_format = VLC_CODEC_SPDIFL FIXME;
             encoding = PA_ENCODING_MPEG_IEC61937;
             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
             break;*/
         case VLC_CODEC_DTS:
-            format = VLC_CODEC_SPDIFL;
+            fmt->i_format = VLC_CODEC_SPDIFL;
             encoding = PA_ENCODING_DTS_IEC61937;
             ss.format = HAVE_FPU ? PA_SAMPLE_FLOAT32NE : PA_SAMPLE_S16NE;
             break;
@@ -780,19 +776,19 @@ static int Open(vlc_object_t *obj)
         default:
             if (HAVE_FPU)
             {
-                format = VLC_CODEC_FL32;
+                fmt->i_format = VLC_CODEC_FL32;
                 ss.format = PA_SAMPLE_FLOAT32NE;
             }
             else
             {
-                format = VLC_CODEC_S16N;
+                fmt->i_format = VLC_CODEC_S16N;
                 ss.format = PA_SAMPLE_S16NE;
             }
             break;
     }
 
-    ss.rate = aout->format.i_rate;
-    ss.channels = aout_FormatNbChannels(&aout->format);
+    ss.rate = fmt->i_rate;
+    ss.channels = aout_FormatNbChannels(fmt);
     if (!pa_sample_spec_valid(&ss)) {
         msg_Err(aout, "unsupported sample specification");
         return VLC_EGENERIC;
@@ -802,28 +798,28 @@ static int Open(vlc_object_t *obj)
     struct pa_channel_map map;
     map.channels = 0;
 
-    if (aout->format.i_physical_channels & AOUT_CHAN_LEFT)
+    if (fmt->i_physical_channels & AOUT_CHAN_LEFT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_RIGHT)
+    if (fmt->i_physical_channels & AOUT_CHAN_RIGHT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLELEFT)
+    if (fmt->i_physical_channels & AOUT_CHAN_MIDDLELEFT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
+    if (fmt->i_physical_channels & AOUT_CHAN_MIDDLERIGHT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_REARLEFT)
+    if (fmt->i_physical_channels & AOUT_CHAN_REARLEFT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_REARRIGHT)
+    if (fmt->i_physical_channels & AOUT_CHAN_REARRIGHT)
         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
-    if (aout->format.i_physical_channels & AOUT_CHAN_REARCENTER)
+    if (fmt->i_physical_channels & AOUT_CHAN_REARCENTER)
         map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
-    if (aout->format.i_physical_channels & AOUT_CHAN_CENTER)
+    if (fmt->i_physical_channels & AOUT_CHAN_CENTER)
     {
         if (ss.channels == 1)
             map.map[map.channels++] = PA_CHANNEL_POSITION_MONO;
         else
             map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
     }
-    if (aout->format.i_physical_channels & AOUT_CHAN_LFE)
+    if (fmt->i_physical_channels & AOUT_CHAN_LFE)
         map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
 
     for (unsigned i = 0; map.channels < ss.channels; i++) {
@@ -859,27 +855,14 @@ static int Open(vlc_object_t *obj)
     attr.minreq = -1;
     attr.fragsize = 0; /* not used for output */
 
-    /* Allocate structures */
-    aout_sys_t *sys = malloc(sizeof(*sys));
-    if (unlikely(sys == NULL))
-        return VLC_ENOMEM;
-
-    pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
-    if (ctx == NULL)
-    {
-        free (sys);
-        return VLC_EGENERIC;
-    }
-
-    aout->sys = sys;
     sys->stream = NULL;
-    sys->context = ctx;
     sys->trigger = NULL;
     sys->first_pts = VLC_TS_INVALID;
     sys->last_pts = VLC_TS_INVALID;
     sys->paused = VLC_TS_INVALID;
     sys->desync = 0;
-    sys->rate = ss.rate;
+    sys->nominal_rate = ss.rate;
+    sys->actual_rate = ss.rate;
 
     /* Channel volume */
     sys->base_volume = PA_VOLUME_NORM;
@@ -916,7 +899,8 @@ static int Open(vlc_object_t *obj)
         pa_proplist_sets (props, PA_PROP_MEDIA_ROLE, "video");
 
     pa_threaded_mainloop_lock(sys->mainloop);
-    s = pa_stream_new_extended(ctx, "audio stream", formatv, formatc, props);
+    s = pa_stream_new_extended(sys->context, "audio stream", formatv, formatc,
+                               props);
     if (likely(props != NULL))
         pa_proplist_free(props);
 
@@ -924,11 +908,12 @@ static int Open(vlc_object_t *obj)
         pa_format_info_free(formatv[i]);
 #else
     pa_threaded_mainloop_lock(sys->mainloop);
-    pa_stream *s = pa_stream_new(ctx, "audio stream", &ss, &map);
+    pa_stream *s = pa_stream_new(sys->context, "audio stream", &ss, &map);
 #endif
     if (s == NULL) {
-        vlc_pa_error(obj, "stream creation failure", ctx);
-        goto fail;
+        pa_threaded_mainloop_unlock(sys->mainloop);
+        vlc_pa_error(aout, "stream creation failure", sys->context);
+        return VLC_EGENERIC;
     }
     sys->stream = s;
     pa_stream_set_state_callback(s, stream_state_cb, sys->mainloop);
@@ -943,7 +928,7 @@ static int Open(vlc_object_t *obj)
 
     if (pa_stream_connect_playback(s, NULL, &attr, flags, NULL, NULL) < 0
      || stream_wait(s, sys->mainloop)) {
-        vlc_pa_error(obj, "stream connection failure", ctx);
+        vlc_pa_error(aout, "stream connection failure", sys->context);
         goto fail;
     }
 
@@ -954,7 +939,7 @@ static int Open(vlc_object_t *obj)
         assert (info != NULL);
         if (pa_format_info_is_pcm (info)) {
             msg_Dbg(aout, "digital pass-through not available");
-            format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
+            fmt->i_format = HAVE_FPU ? VLC_CODEC_FL32 : VLC_CODEC_S16N;
         } else {
             msg_Dbg(aout, "digital pass-through enabled");
             pa_stream_set_latency_update_callback(s, NULL, NULL);
@@ -968,7 +953,7 @@ static int Open(vlc_object_t *obj)
                &(vlc_value_t){ .psz_string = (char *)_("Audio device") },
                NULL);
     var_AddCallback (aout, "audio-device", StreamMove, s);
-    op = pa_context_get_sink_info_list(ctx, sink_list_cb, aout);
+    op = pa_context_get_sink_info_list(sys->context, sink_list_cb, aout);
     /* We may need to wait for completion... once LibVLC supports this */
     if (op != NULL)
         pa_operation_unref(op);
@@ -977,61 +962,90 @@ static int Open(vlc_object_t *obj)
     /* Context events */
     const pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SINK
                                       | PA_SUBSCRIPTION_MASK_SINK_INPUT;
-    pa_context_set_subscribe_callback(ctx, context_cb, aout);
-    op = pa_context_subscribe(ctx, mask, NULL, NULL);
+    pa_context_set_subscribe_callback(sys->context, context_cb, aout);
+    op = pa_context_subscribe(sys->context, mask, NULL, NULL);
     if (likely(op != NULL))
        pa_operation_unref(op);
     pa_threaded_mainloop_unlock(sys->mainloop);
 
-    aout->format.i_format = format;
-    aout->play = Play;
-    aout->pause = Pause;
-    aout->flush = Flush;
-    aout->volume_set = VolumeSet;
-    aout->mute_set = MuteSet;
     return VLC_SUCCESS;
 
 fail:
     pa_threaded_mainloop_unlock(sys->mainloop);
-    Close(obj);
+    Stop(aout);
     return VLC_EGENERIC;
 }
 
 /**
  * Removes a PulseAudio playback stream
  */
-static void Close (vlc_object_t *obj)
+static void Stop(audio_output_t *aout)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
-    pa_context *ctx = sys->context;
     pa_stream *s = sys->stream;
 
-    if (s != NULL) {
-        /* The callback takes mainloop lock, so it CANNOT be held here! */
-        var_DelCallback (aout, "audio-device", StreamMove, s);
-        var_Destroy (aout, "audio-device");
-
-        pa_threaded_mainloop_lock(sys->mainloop);
-        if (unlikely(sys->trigger != NULL))
-            vlc_pa_rttime_free(sys->mainloop, sys->trigger);
-        pa_stream_disconnect(s);
-
-        /* Clear all callbacks */
-        pa_stream_set_state_callback(s, NULL, NULL);
-        pa_stream_set_buffer_attr_callback(s, NULL, NULL);
-        pa_stream_set_event_callback(s, NULL, NULL);
-        pa_stream_set_latency_update_callback(s, NULL, NULL);
-        pa_stream_set_moved_callback(s, NULL, NULL);
-        pa_stream_set_overflow_callback(s, NULL, NULL);
-        pa_stream_set_started_callback(s, NULL, NULL);
-        pa_stream_set_suspended_callback(s, NULL, NULL);
-        pa_stream_set_underflow_callback(s, NULL, NULL);
-        pa_context_set_subscribe_callback(ctx, NULL, NULL);
-
-        pa_stream_unref(s);
-        pa_threaded_mainloop_unlock(sys->mainloop);
+    /* The callback takes mainloop lock, so it CANNOT be held here! */
+    var_DelCallback (aout, "audio-device", StreamMove, s);
+    var_Destroy (aout, "audio-device");
+
+    pa_threaded_mainloop_lock(sys->mainloop);
+    if (unlikely(sys->trigger != NULL))
+        vlc_pa_rttime_free(sys->mainloop, sys->trigger);
+    pa_stream_disconnect(s);
+
+    /* Clear all callbacks */
+    pa_stream_set_state_callback(s, NULL, NULL);
+    pa_stream_set_buffer_attr_callback(s, NULL, NULL);
+    pa_stream_set_event_callback(s, NULL, NULL);
+    pa_stream_set_latency_update_callback(s, NULL, NULL);
+    pa_stream_set_moved_callback(s, NULL, NULL);
+    pa_stream_set_overflow_callback(s, NULL, NULL);
+    pa_stream_set_started_callback(s, NULL, NULL);
+    pa_stream_set_suspended_callback(s, NULL, NULL);
+    pa_stream_set_underflow_callback(s, NULL, NULL);
+    pa_context_set_subscribe_callback(sys->context, NULL, NULL);
+
+    pa_stream_unref(s);
+    pa_threaded_mainloop_unlock(sys->mainloop);
+}
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc(sizeof (*sys));
+
+#if !PA_CHECK_VERSION(0,9,22)
+    if (!vlc_xlib_init(obj))
+        return VLC_EGENERIC;
+#endif
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    /* Allocate structures */
+    pa_context *ctx = vlc_pa_connect(obj, &sys->mainloop);
+    if (ctx == NULL)
+    {
+        free(sys);
+        return VLC_EGENERIC;
     }
+    sys->context = ctx;
+
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->play = Play;
+    aout->pause = Pause;
+    aout->flush = Flush;
+    aout->volume_set = VolumeSet;
+    aout->mute_set = MuteSet;
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+    pa_context *ctx = sys->context;
 
     vlc_pa_disconnect(obj, ctx, sys->mainloop);
     free(sys);
index f52f4a9a0d22caadd7ba726cbac869a8cc8e77d1..4ec390ec3860eb02d18b98f97324327f7d6a0a4f 100644 (file)
@@ -32,7 +32,7 @@
 #include <sndio.h>
 
 static int Open (vlc_object_t *);
-static void Close (vlc_object_t *);
+static void Close (vlc_objec_t *);
 
 vlc_module_begin ()
     set_shortname ("sndio")
@@ -40,7 +40,7 @@ vlc_module_begin ()
     set_category (CAT_AUDIO)
     set_subcategory (SUBCAT_AUDIO_AOUT)
     set_capability ("audio output", 120)
-    set_callbacks (Open, Close )
+    set_callbacks (Open, Close)
 vlc_module_end ()
 
 static void Play (audio_output_t *, block_t *, mtime_t *);
@@ -57,12 +57,9 @@ struct aout_sys_t
 };
 
 /** Initializes an sndio playback stream */
-static int Open (vlc_object_t *obj)
+static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
-    aout_sys_t *sys = malloc (sizeof (*sys));
-    if (unlikely(sys == NULL))
-        return VLC_EGENERIC;
+    aout_sys_t *sys = aout->sys;
 
     sys->hdl = sio_open (NULL, SIO_PLAY, 0 /* blocking */);
     if (sys->hdl == NULL)
@@ -79,8 +76,8 @@ static int Open (vlc_object_t *obj)
     par.bps = par.bits >> 3;
     par.sig = 1;
     par.le = SIO_LE_NATIVE;
-    par.pchan = aout_FormatNbChannels (&aout->format);
-    par.rate = aout->format.i_rate;
+    par.pchan = aout_FormatNbChannels (fmt);
+    par.rate = fmt->i_rate;
     par.xrun = SIO_SYNC;
 
     if (!sio_setpar (sys->hdl, &par) || !sio_getpar (sys->hdl, &par))
@@ -96,23 +93,24 @@ static int Open (vlc_object_t *obj)
         goto error;
     }
 
-    audio_format_t f;
-
     switch (par.bits)
     {
         case 8:
-            f.i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
+            fmt->i_format = par.sig ? VLC_CODEC_S8 : VLC_CODEC_U8;
             break;
         case 16:
-            f.i_format = par.sig ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
+            fmt->i_format = par.sig
+                                 ? (par.le ? VLC_CODEC_S16L : VLC_CODEC_S16B)
                                  : (par.le ? VLC_CODEC_U16L : VLC_CODEC_U16B);
             break;
         case 24:
-            f.i_format = par.sig ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
+            fmt->i_format = par.sig
+                                 ? (par.le ? VLC_CODEC_S24L : VLC_CODEC_S24B)
                                  : (par.le ? VLC_CODEC_U24L : VLC_CODEC_U24B);
             break;
         case 32:
-            f.i_format = par.sig ? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B)
+            fmt->i_format = par.sig
+                                 ? (par.le ? VLC_CODEC_S32L : VLC_CODEC_S32B)
                                  : (par.le ? VLC_CODEC_U32L : VLC_CODEC_U32B);
             break;
         default:
@@ -121,7 +119,7 @@ static int Open (vlc_object_t *obj)
             goto error;
     }
 
-    f.i_rate = par.rate;
+    fmt->i_rate = par.rate;
 
     /* Channel map */
     unsigned chans;
@@ -147,10 +145,9 @@ static int Open (vlc_object_t *obj)
             goto error;
     }
 
-    f.i_original_channels = f.i_physical_channels = chans;
-    aout_FormatPrepare (&f);
+    fmt->i_original_channels = fmt->i_physical_channels = chans;
+    aout_FormatPrepare (fmt);
 
-    aout->format = f;
     aout->sys = sys;
     aout->play = Play;
     aout->pause = Pause;
@@ -170,7 +167,7 @@ static int Open (vlc_object_t *obj)
     return VLC_SUCCESS;
 
 error:
-    Close (obj);
+    sio_close (sys->hdl);
     return VLC_EGENERIC;
 }
 
@@ -180,7 +177,6 @@ static void Close (vlc_object_t *obj)
     aout_sys_t *sys = aout->sys;
 
     sio_close (sys->hdl);
-    free (sys);
 }
 
 static void Play (audio_output_t *aout, block_t *block,
@@ -250,3 +246,26 @@ static int MuteSet (audio_output_t *aout, bool mute)
     sys->mute = mute;
     return 0;
 }
+
+static int Open (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc (sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    /* FIXME: set volume/mute here */
+    return VLC_SUCCESS;
+}
+
+static int Close (vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free (sys);
+}
+
index fd5ddda0ded0ac4531d008e00fb16134c94592ac..ffea008ddba5137e178428c020e6d09a57b1ea91 100644 (file)
@@ -121,6 +121,8 @@ struct aout_sys_t
     struct IAudioSessionEvents events;
     LONG refs;
 
+    unsigned rate; /**< Sample rate */
+    unsigned bytes_per_frame;
     UINT32 frames; /**< Total buffer size (frames) */
     HANDLE ready; /**< Semaphore from MTA thread */
     HANDLE done; /**< Semaphore to MTA thread */
@@ -173,7 +175,7 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
             break;
         }
 
-        const size_t copy = frames * (size_t)aout->format.i_bytes_per_frame;
+        const size_t copy = frames * sys->bytes_per_frame;
 
         memcpy(dst, block->p_buffer, copy);
         hr = IAudioRenderClient_ReleaseBuffer(sys->render, frames, 0);
@@ -192,7 +194,7 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
 
         /* Out of buffer space, sleep */
         msleep(AOUT_MIN_PREPARE_TIME
-             + block->i_nb_samples * CLOCK_FREQ / aout->format.i_rate);
+             + block->i_nb_samples * CLOCK_FREQ / sys->rate);
     }
 
     Leave();
@@ -653,20 +655,11 @@ fail:
     ReleaseSemaphore(sys->ready, 1, NULL);
 }
 
-static int Open(vlc_object_t *obj)
+static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
     HRESULT hr;
 
-    if (AOUT_FMT_SPDIF(&aout->format) && !aout->b_force
-     && var_InheritBool(aout, "spdif"))
-        /* Fallback to other plugin until pass-through is implemented */
-        return VLC_EGENERIC;
-
-    aout_sys_t *sys = malloc(sizeof (*sys));
-    if (unlikely(sys == NULL))
-        return VLC_ENOMEM;
-    sys->aout = aout;
     sys->client = NULL;
     sys->render = NULL;
     sys->clock = NULL;
@@ -674,17 +667,8 @@ static int Open(vlc_object_t *obj)
     sys->refs = 1;
     sys->ready = NULL;
     sys->done = NULL;
-    aout->sys = sys;
-
-    if (TryEnter(aout))
-    {
-        free(sys);
-        return VLC_EGENERIC;
-    }
-retry:
-    /* Get audio device according to policy */
-    var_Create (aout, "audio-device", VLC_VAR_STRING|VLC_VAR_HASCHOICE);
 
+    Enter();
     IMMDeviceEnumerator *devs;
     hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
                           &IID_IMMDeviceEnumerator, (void **)&devs);
@@ -693,6 +677,9 @@ retry:
         msg_Dbg(aout, "cannot create device enumerator (error 0x%lx)", hr);
         goto error;
     }
+retry:
+    /* Get audio device according to policy */
+    var_Create (aout, "audio-device", VLC_VAR_STRING|VLC_VAR_HASCHOICE);
 
     // Without configuration item, the variable must be created explicitly.
     var_Create (aout, "wasapi-audio-device", VLC_VAR_STRING);
@@ -741,11 +728,10 @@ retry:
     }
 
     /* Configure audio stream */
-    audio_sample_format_t format = aout->format;
     WAVEFORMATEXTENSIBLE wf;
     WAVEFORMATEX *pwf;
 
-    vlc_ToWave(&wf, &format);
+    vlc_ToWave(&wf, fmt);
     hr = IAudioClient_IsFormatSupported(sys->client, AUDCLNT_SHAREMODE_SHARED,
                                         &wf.Format, &pwf);
     if (FAILED(hr))
@@ -757,7 +743,7 @@ retry:
     if (hr == S_FALSE)
     {
         assert(pwf != NULL);
-        if (vlc_FromWave(pwf, &format))
+        if (vlc_FromWave(pwf, fmt))
         {
             CoTaskMemFree(pwf);
             msg_Err(aout, "unsupported audio format");
@@ -799,15 +785,11 @@ retry:
 
     Leave();
 
-    aout->format = format;
+    sys->rate = fmt->i_rate;
+    sys->bytes_per_frame = fmt->i_bytes_per_frame;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
-    /*if (AOUT_FMT_LINEAR(&format) && !exclusive)*/
-    {
-        aout->volume_set = SimpleVolumeSet;
-        aout->mute_set = SimpleMuteSet;
-    }
     if (likely(sys->control != NULL))
        IAudioSessionControl_RegisterAudioSessionNotification(sys->control,
                                                              &sys->events);
@@ -828,13 +810,11 @@ error:
         goto retry;
     }
     Leave();
-    free(sys);
     return VLC_EGENERIC;
 }
 
-static void Close (vlc_object_t *obj)
+static void Stop(audio_output_t *aout)
 {
-    audio_output_t *aout = (audio_output_t *)obj;
     aout_sys_t *sys = aout->sys;
 
     Enter();
@@ -852,5 +832,40 @@ static void Close (vlc_object_t *obj)
 
     CloseHandle(sys->done);
     CloseHandle(sys->ready);
+}
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+
+    if (!aout->b_force && var_InheritBool(aout, "spdif"))
+        /* Fallback to other plugin until pass-through is implemented */
+        return VLC_EGENERIC;
+
+    aout_sys_t *sys = malloc(sizeof (*sys));
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+
+    if (TryEnter(aout))
+    {
+        free(sys);
+        return VLC_EGENERIC;
+    }
+    Leave();
+
+    sys->aout = aout;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    aout->volume_set = SimpleVolumeSet; /* FIXME */
+    aout->mute_set = SimpleMuteSet;
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
     free(sys);
 }
index 90554b97bc68f49e6957041532b2a9ed9a99f9ae..8516676257c19c2c7b56b808de5fbfecbf9534c8 100644 (file)
@@ -57,7 +57,7 @@ static void Play         ( audio_output_t *, block_t *, mtime_t * );
  * notification_thread_t: waveOut event thread
  *****************************************************************************/
 /* local functions */
-static void Probe        ( audio_output_t * );
+static void Probe        ( audio_output_t *, const audio_sample_format_t * );
 static int OpenWaveOut   ( audio_output_t *, uint32_t,
                            int, int, int, int, bool );
 static int OpenWaveOutPCM( audio_output_t *, uint32_t,
@@ -153,21 +153,14 @@ vlc_module_begin ()
 vlc_module_end ()
 
 /*****************************************************************************
- * Open: open the audio device
+ * Opens the audio device
  *****************************************************************************
  * This function opens and setups Win32 waveOut
  *****************************************************************************/
-static int Open( vlc_object_t *p_this )
+static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     vlc_value_t val;
 
-    /* Allocate structure */
-    p_aout->sys = malloc( sizeof( aout_sys_t ) );
-
-    if( p_aout->sys == NULL )
-        return VLC_ENOMEM;
-
     p_aout->play = Play;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
@@ -211,7 +204,7 @@ static int Open( vlc_object_t *p_this )
 
     if( var_Type( p_aout, "audio-device" ) == 0 )
     {
-        Probe( p_aout );
+        Probe( p_aout, fmt );
     }
 
     if( var_Get( p_aout, "audio-device", &val ) < 0 )
@@ -226,14 +219,11 @@ static int Open( vlc_object_t *p_this )
     /* Open the device */
     if( val.i_int == AOUT_VAR_SPDIF )
     {
-        p_aout->format.i_format = VLC_CODEC_SPDIFL;
-
-        if( OpenWaveOut( p_aout,
-                         p_aout->sys->i_wave_device_id,
-                         VLC_CODEC_SPDIFL,
-                         p_aout->format.i_physical_channels,
-                         aout_FormatNbChannels( &p_aout->format ),
-                         p_aout->format.i_rate, false )
+        fmt->i_format = VLC_CODEC_SPDIFL;
+
+        if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
+                         VLC_CODEC_SPDIFL, fmt->i_physical_channels,
+                         aout_FormatNbChannels( fmt ), fmt->i_rate, false )
             != VLC_SUCCESS )
         {
             msg_Err( p_aout, "cannot open waveout audio device" );
@@ -242,14 +232,11 @@ static int Open( vlc_object_t *p_this )
         }
 
         /* Calculate the frame size in bytes */
-        p_aout->format.i_bytes_per_frame = AOUT_SPDIF_SIZE;
-        p_aout->format.i_frame_length = A52_FRAME_NB;
-        p_aout->sys->i_buffer_size =
-            p_aout->format.i_bytes_per_frame;
-
-        aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB );
-        p_aout->volume_set = NULL;
-        p_aout->mute_set = NULL;
+        fmt->i_bytes_per_frame = AOUT_SPDIF_SIZE;
+        fmt->i_frame_length = A52_FRAME_NB;
+        p_aout->sys->i_buffer_size = fmt->i_bytes_per_frame;
+
+        aout_PacketInit( p_aout, &p_aout->sys->packet, A52_FRAME_NB, fmt );
     }
     else
     {
@@ -258,30 +245,26 @@ static int Open( vlc_object_t *p_this )
         switch( val.i_int )
         {
         case AOUT_VAR_5_1:
-            p_aout->format.i_physical_channels
+            fmt->i_physical_channels
                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
                       | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
                       | AOUT_CHAN_LFE;
             break;
         case AOUT_VAR_2F2R:
-            p_aout->format.i_physical_channels
+            fmt->i_physical_channels
                     = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                       | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
             break;
         case AOUT_VAR_MONO:
-            p_aout->format.i_physical_channels = AOUT_CHAN_CENTER;
+            fmt->i_physical_channels = AOUT_CHAN_CENTER;
             break;
         default:
-            p_aout->format.i_physical_channels
-                    = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
+            fmt->i_physical_channels = AOUT_CHANS_STEREO;
         }
 
-        if( OpenWaveOutPCM( p_aout,
-                            p_aout->sys->i_wave_device_id,
-                            &p_aout->format.i_format,
-                            p_aout->format.i_physical_channels,
-                            aout_FormatNbChannels( &p_aout->format ),
-                            p_aout->format.i_rate, false )
+        if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
+                            &fmt->i_format, fmt->i_physical_channels,
+                            aout_FormatNbChannels( fmt ), fmt->i_rate, false )
             != VLC_SUCCESS )
         {
             msg_Err( p_aout, "cannot open waveout audio device" );
@@ -290,17 +273,16 @@ static int Open( vlc_object_t *p_this )
         }
 
         /* Calculate the frame size in bytes */
-        aout_FormatPrepare( &p_aout->format );
-        p_aout->sys->i_buffer_size = FRAME_SIZE *
-            p_aout->format.i_bytes_per_frame;
+        aout_FormatPrepare( fmt );
+        p_aout->sys->i_buffer_size = FRAME_SIZE * fmt->i_bytes_per_frame;
 
-        aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE );
+        aout_PacketInit( p_aout, &p_aout->sys->packet, FRAME_SIZE, fmt );
 
         /* Check for hardware volume support */
         if( waveOutGetDevCaps( (UINT_PTR)p_aout->sys->h_waveout,
                                &wocaps, sizeof(wocaps) ) == MMSYSERR_NOERROR
          && (wocaps.dwSupport & WAVECAPS_VOLUME) )
-        {
+        {   /* FIXME: this needs to be moved to Open() */
             p_aout->volume_set = VolumeSet;
             p_aout->mute_set = MuteSet;
             p_aout->sys->volume = 0xffff.fp0;
@@ -360,7 +342,7 @@ static int Open( vlc_object_t *p_this )
 /*****************************************************************************
  * Probe: probe the audio device for available formats and channels
  *****************************************************************************/
-static void Probe( audio_output_t * p_aout )
+static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
 {
     vlc_value_t val, text;
     vlc_fourcc_t i_format;
@@ -374,13 +356,11 @@ static void Probe( audio_output_t * p_aout )
     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                           AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT |
                           AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE;
-    if( p_aout->format.i_physical_channels == i_physical_channels )
+    if( fmt->i_physical_channels == i_physical_channels )
     {
-        if( OpenWaveOutPCM( p_aout,
-                            p_aout->sys->i_wave_device_id,
-                            &i_format,
-                            i_physical_channels, 6,
-                            p_aout->format.i_rate, true )
+        if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
+                            &i_format, i_physical_channels, 6,
+                            fmt->i_rate, true )
             == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_5_1;
@@ -394,14 +374,12 @@ static void Probe( audio_output_t * p_aout )
     /* Test for 2 Front 2 Rear support */
     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                           AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
-    if( ( p_aout->format.i_physical_channels & i_physical_channels )
+    if( ( fmt->i_physical_channels & i_physical_channels )
         == i_physical_channels )
     {
-        if( OpenWaveOutPCM( p_aout,
-                            p_aout->sys->i_wave_device_id,
-                            &i_format,
-                            i_physical_channels, 4,
-                            p_aout->format.i_rate, true )
+        if( OpenWaveOutPCM( p_aout,p_aout->sys->i_wave_device_id,
+                            &i_format, i_physical_channels, 4,
+                            fmt->i_rate, true )
             == VLC_SUCCESS )
         {
             val.i_int = AOUT_VAR_2F2R;
@@ -414,11 +392,9 @@ static void Probe( audio_output_t * p_aout )
 
     /* Test for stereo support */
     i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
-    if( OpenWaveOutPCM( p_aout,
-                        p_aout->sys->i_wave_device_id,
-                        &i_format,
-                        i_physical_channels, 2,
-                        p_aout->format.i_rate, true )
+    if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
+                        &i_format,i_physical_channels, 2,
+                        fmt->i_rate, true )
         == VLC_SUCCESS )
     {
         val.i_int = AOUT_VAR_STEREO;
@@ -429,11 +405,8 @@ static void Probe( audio_output_t * p_aout )
 
     /* Test for mono support */
     i_physical_channels = AOUT_CHAN_CENTER;
-    if( OpenWaveOutPCM( p_aout,
-                        p_aout->sys->i_wave_device_id,
-                        &i_format,
-                        i_physical_channels, 1,
-                        p_aout->format.i_rate, true )
+    if( OpenWaveOutPCM( p_aout, p_aout->sys->i_wave_device_id,
+                        &i_format, i_physical_channels, 1, fmt->i_rate, true )
         == VLC_SUCCESS )
     {
         val.i_int = AOUT_VAR_MONO;
@@ -443,14 +416,11 @@ static void Probe( audio_output_t * p_aout )
     }
 
     /* Test for SPDIF support */
-    if ( AOUT_FMT_SPDIF( &p_aout->format ) )
+    if ( AOUT_FMT_SPDIF( fmt ) )
     {
-        if( OpenWaveOut( p_aout,
-                         p_aout->sys->i_wave_device_id,
-                         VLC_CODEC_SPDIFL,
-                         p_aout->format.i_physical_channels,
-                         aout_FormatNbChannels( &p_aout->format ),
-                         p_aout->format.i_rate, true )
+        if( OpenWaveOut( p_aout, p_aout->sys->i_wave_device_id,
+                         VLC_CODEC_SPDIFL, fmt->i_physical_channels,
+                         aout_FormatNbChannels( fmt ), fmt->i_rate, true )
             == VLC_SUCCESS )
         {
             msg_Dbg( p_aout, "device supports A/52 over S/PDIF" );
@@ -504,9 +474,8 @@ static void Play( audio_output_t *_p_aout, block_t *block,
 /*****************************************************************************
  * Close: close the audio device
  *****************************************************************************/
-static void Close( vlc_object_t *p_this )
+static void Stop( audio_output_t *p_aout )
 {
-    audio_output_t *p_aout = (audio_output_t *)p_this;
     aout_sys_t *p_sys = p_aout->sys;
 
     /* Before calling waveOutClose we must reset the device */
@@ -575,7 +544,6 @@ static void Close( vlc_object_t *p_this )
 
     free( p_sys->p_silence_buffer );
     aout_PacketDestroy( p_aout );
-    free( p_sys );
 }
 
 /*****************************************************************************
@@ -886,7 +854,7 @@ static void* WaveOutThread( void *data )
     int canc = vlc_savecancel ();
 
     /* We don't want any resampling when using S/PDIF */
-    b_sleek = p_aout->format.i_format == VLC_CODEC_SPDIFL;
+    b_sleek = p_sys->packet.format.i_format == VLC_CODEC_SPDIFL;
 
     // wait for first call to "play()"
     while( !p_sys->start_date && !vlc_atomic_get(&p_aout->sys->abort) )
@@ -1099,3 +1067,25 @@ static uint32_t findDeviceID(char *psz_device_name)
 
     return WAVE_MAPPER;
 }
+
+static int Open(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = malloc(sizeof (*sys));
+
+    if (unlikely(sys == NULL))
+        return VLC_ENOMEM;
+    aout->sys = sys;
+    aout->start = Start;
+    aout->stop = Stop;
+    /* FIXME: volume handlers */
+    return VLC_SUCCESS;
+}
+
+static void Close(vlc_object_t *obj)
+{
+    audio_output_t *aout = (audio_output_t *)obj;
+    aout_sys_t *sys = aout->sys;
+
+    free(sys);
+}
index a5f7e67d1367deff8623cdef3c79b4514bed7b81..dd48fde4b904be1f2567221d685f425c609c63c1 100644 (file)
@@ -76,64 +76,71 @@ static int aout_OutputGainRequest (audio_output_t *aout, float gain)
  *****************************************************************************
  * This function is entered with the mixer lock.
  *****************************************************************************/
-int aout_OutputNew( audio_output_t *p_aout,
-                    const audio_sample_format_t * p_format )
+int aout_OutputNew (audio_output_t *aout, const audio_sample_format_t *fmtp)
 {
-    aout_owner_t *owner = aout_owner (p_aout);
+    aout_owner_t *owner = aout_owner (aout);
+
+    audio_sample_format_t fmt = *fmtp;
+    aout_FormatPrepare (&fmt);
 
-    aout_assert_locked( p_aout );
-    p_aout->format = *p_format;
-    aout_FormatPrepare( &p_aout->format );
+    aout_assert_locked (aout);
 
-    p_aout->event.volume_report = aout_OutputVolumeReport;
-    p_aout->event.mute_report = aout_OutputMuteReport;
-    p_aout->event.policy_report = aout_OutputPolicyReport;
-    p_aout->event.gain_request = aout_OutputGainRequest;
+    aout->event.volume_report = aout_OutputVolumeReport;
+    aout->event.mute_report = aout_OutputMuteReport;
+    aout->event.policy_report = aout_OutputPolicyReport;
+    aout->event.gain_request = aout_OutputGainRequest;
 
     /* Find the best output plug-in. */
-    owner->module = module_need (p_aout, "audio output", "$aout", false);
+    owner->module = module_need (aout, "audio output", "$aout", false);
     if (owner->module == NULL)
     {
-        msg_Err( p_aout, "no suitable audio output module" );
+        msg_Err (aout, "no suitable audio output module");
+        return -1;
+    }
+
+    if (aout->start (aout, &fmt))
+    {
+        msg_Err (aout, "module not functional");
+        module_unneed (aout, owner->module);
+        owner->module = NULL;
         return -1;
     }
 
-    if (!var_Type (p_aout, "stereo-mode"))
-        var_Create (p_aout, "stereo-mode",
+    if (!var_Type (aout, "stereo-mode"))
+        var_Create (aout, "stereo-mode",
                     VLC_VAR_INTEGER | VLC_VAR_HASCHOICE | VLC_VAR_DOINHERIT);
 
     /* The user may have selected a different channels configuration. */
-    var_AddCallback (p_aout, "stereo-mode", aout_ChannelsRestart, NULL);
-    switch (var_GetInteger (p_aout, "stereo-mode"))
+    var_AddCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
+    switch (var_GetInteger (aout, "stereo-mode"))
     {
         case AOUT_VAR_CHAN_RSTEREO:
-            p_aout->format.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
+            fmt.i_original_channels |= AOUT_CHAN_REVERSESTEREO;
              break;
         case AOUT_VAR_CHAN_STEREO:
-            p_aout->format.i_original_channels = AOUT_CHANS_STEREO;
+            fmt.i_original_channels = AOUT_CHANS_STEREO;
             break;
         case AOUT_VAR_CHAN_LEFT:
-            p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
+            fmt.i_original_channels = AOUT_CHAN_LEFT;
             break;
         case AOUT_VAR_CHAN_RIGHT:
-            p_aout->format.i_original_channels = AOUT_CHAN_RIGHT;
+            fmt.i_original_channels = AOUT_CHAN_RIGHT;
             break;
         case AOUT_VAR_CHAN_DOLBYS:
-            p_aout->format.i_original_channels =
-                                     AOUT_CHANS_STEREO | AOUT_CHAN_DOLBYSTEREO;
+            fmt.i_original_channels = AOUT_CHANS_STEREO|AOUT_CHAN_DOLBYSTEREO;
             break;
         default:
         {
-            if ((p_aout->format.i_original_channels & AOUT_CHAN_PHYSMASK)
+            if ((fmt.i_original_channels & AOUT_CHAN_PHYSMASK)
                                                          != AOUT_CHANS_STEREO)
                  break;
 
             vlc_value_t val, txt;
             val.i_int = 0;
-            var_Change (p_aout, "stereo-mode", VLC_VAR_DELCHOICE, &val, NULL);
+            var_Change (aout, "stereo-mode", VLC_VAR_DELCHOICE, &val, NULL);
             txt.psz_string = _("Stereo audio mode");
-            var_Change (p_aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);
-            if (p_aout->format.i_original_channels & AOUT_CHAN_DOLBYSTEREO)
+            var_Change (aout, "stereo-mode", VLC_VAR_SETTEXT, &txt, NULL);
+            if (fmt.i_original_channels & AOUT_CHAN_DOLBYSTEREO)
             {
                 val.i_int = AOUT_VAR_CHAN_DOLBYS;
                 txt.psz_string = _("Dolby Surround");
@@ -143,33 +150,32 @@ int aout_OutputNew( audio_output_t *p_aout,
                 val.i_int = AOUT_VAR_CHAN_STEREO;
                 txt.psz_string = _("Stereo");
             }
-            var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
-            var_Change (p_aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
+            var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
+            var_Change (aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
             val.i_int = AOUT_VAR_CHAN_LEFT;
             txt.psz_string = _("Left");
-            var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
-            if (p_aout->format.i_original_channels & AOUT_CHAN_DUALMONO)
+            var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
+            if (fmt.i_original_channels & AOUT_CHAN_DUALMONO)
             {   /* Go directly to the left channel. */
-                p_aout->format.i_original_channels = AOUT_CHAN_LEFT;
-                var_Change (p_aout, "stereo-mode", VLC_VAR_SETVALUE, &val,
-                            NULL);
+                fmt.i_original_channels = AOUT_CHAN_LEFT;
+                var_Change (aout, "stereo-mode", VLC_VAR_SETVALUE, &val, NULL);
             }
             val.i_int = AOUT_VAR_CHAN_RIGHT;
             txt.psz_string = _("Right");
-            var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
+            var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
             val.i_int = AOUT_VAR_CHAN_RSTEREO;
             txt.psz_string = _("Reverse stereo");
-            var_Change (p_aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
+            var_Change (aout, "stereo-mode", VLC_VAR_ADDCHOICE, &val, &txt);
         }
     }
 
-    aout_FormatPrepare( &p_aout->format );
-    aout_FormatPrint( p_aout, "output", &p_aout->format );
+    aout_FormatPrepare (&fmt);
+    aout_FormatPrint (aout, "output", &fmt );
 
     /* Choose the mixer format. */
-    owner->mixer_format = p_aout->format;
-    if (!AOUT_FMT_LINEAR(&p_aout->format))
-        owner->mixer_format.i_format = p_format->i_format;
+    owner->mixer_format = fmt;
+    if (!AOUT_FMT_LINEAR(&fmt))
+        owner->mixer_format.i_format = fmtp->i_format;
     else
     /* Most audio filters can only deal with single-precision,
      * so lets always use that when hardware supports floating point. */
@@ -181,16 +187,15 @@ int aout_OutputNew( audio_output_t *p_aout,
         owner->mixer_format.i_format = VLC_CODEC_S16N;
 
     aout_FormatPrepare (&owner->mixer_format);
-    aout_FormatPrint (p_aout, "mixer", &owner->mixer_format);
+    aout_FormatPrint (aout, "mixer", &owner->mixer_format);
 
     /* Create filters. */
     owner->nb_filters = 0;
-    if (aout_FiltersCreatePipeline (p_aout, owner->filters,
-                                    &owner->nb_filters, &owner->mixer_format,
-                                    &p_aout->format) < 0)
+    if (aout_FiltersCreatePipeline (aout, owner->filters, &owner->nb_filters,
+                                    &owner->mixer_format, &fmt) < 0)
     {
-        msg_Err( p_aout, "couldn't create audio output pipeline" );
-        module_unneed (p_aout, owner->module);
+        msg_Err (aout, "couldn't create audio output pipeline");
+        module_unneed (aout, owner->module);
         owner->module = NULL;
         return -1;
     }
@@ -210,6 +215,8 @@ void aout_OutputDelete (audio_output_t *aout)
         return;
 
     var_DelCallback (aout, "stereo-mode", aout_ChannelsRestart, NULL);
+    if (aout->stop != NULL)
+        aout->stop (aout);
     module_unneed (aout, owner->module);
     aout->volume_set = NULL;
     aout->mute_set = NULL;