1 /*****************************************************************************
2 * audioqueue.c : AudioQueue audio output plugin for vlc
3 *****************************************************************************
4 * Copyright (C) 2010-2012 VLC authors and VideoLAN
7 * Authors: Romain Goyet <romain.goyet@likid.org>
8 * Felix Paul Kühne <fkuehne@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
36 #include <AudioToolBox/AudioToolBox.h>
38 #define FRAME_SIZE 2048
40 /*****************************************************************************
41 * aout_sys_t: AudioQueue audio output method descriptor
42 *****************************************************************************
43 * This structure is part of the audio output thread descriptor.
44 * It describes the specific properties of an audio device.
45 *****************************************************************************/
48 AudioQueueRef audioQueue;
52 /*****************************************************************************
54 *****************************************************************************/
55 static int Open (vlc_object_t *);
56 static void Close (vlc_object_t *);
57 static void Play (audio_output_t *, block_t *);
58 static void Pause (audio_output_t *p_aout, bool pause, mtime_t date);
59 static void Flush (audio_output_t *p_aout, bool wait);
60 static int TimeGet (audio_output_t *aout, mtime_t *);
61 static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef);
63 /*****************************************************************************
65 *****************************************************************************/
67 set_shortname("AudioQueue")
68 set_description(N_("AudioQueue (iOS / Mac OS) audio output"))
69 set_capability("audio output", 40)
70 set_category(CAT_AUDIO)
71 set_subcategory(SUBCAT_AUDIO_AOUT)
72 add_shortcut("audioqueue")
73 set_callbacks(Open, Close)
76 /*****************************************************************************
77 * Start: open the audio device
78 *****************************************************************************/
80 static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
82 aout_sys_t *p_sys = p_aout->sys;
85 // Setup the audio device.
86 AudioStreamBasicDescription deviceFormat;
87 deviceFormat.mSampleRate = 44100;
88 deviceFormat.mFormatID = kAudioFormatLinearPCM;
89 deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; // Signed integer, little endian
90 deviceFormat.mBytesPerPacket = 4;
91 deviceFormat.mFramesPerPacket = 1;
92 deviceFormat.mBytesPerFrame = 4;
93 deviceFormat.mChannelsPerFrame = 2;
94 deviceFormat.mBitsPerChannel = 16;
95 deviceFormat.mReserved = 0;
97 // Create a new output AudioQueue for the device.
98 status = AudioQueueNewOutput(&deviceFormat, // Format
99 AudioQueueCallback, // Callback
100 NULL, // User data, passed to the callback
101 CFRunLoopGetMain(), // RunLoop
102 kCFRunLoopCommonModes, // RunLoop mode
103 0, // Flags ; must be zero (per documentation)...
104 &(p_sys->audioQueue)); // Output
106 msg_Dbg(p_aout, "New AudioQueue output created (status = %i)", status);
110 fmt->i_format = VLC_CODEC_S16L;
111 fmt->i_physical_channels = AOUT_CHANS_STEREO;
113 aout_FormatPrepare(fmt);
115 p_aout->sys->b_stopped = false;
117 status = AudioQueueStart(p_sys->audioQueue, NULL);
118 msg_Dbg(p_aout, "Starting AudioQueue (status = %i)", status);
120 p_aout->time_get = TimeGet;
122 p_aout->pause = Pause;
123 p_aout->flush = Flush;
131 /*****************************************************************************
132 * Stop: close the audio device
133 *****************************************************************************/
135 static void Stop (audio_output_t *p_aout)
137 p_aout->sys->b_stopped = true;
139 msg_Dbg(p_aout, "Stopping AudioQueue");
140 AudioQueueStop(p_aout->sys->audioQueue, true);
141 msg_Dbg(p_aout, "Disposing AudioQueue");
142 AudioQueueDispose(p_aout->sys->audioQueue, true);
145 /*****************************************************************************
147 *****************************************************************************/
149 static void Play (audio_output_t *p_aout, block_t *p_block)
151 if (p_block != NULL) {
152 AudioQueueBufferRef inBuffer = NULL;
155 status = AudioQueueAllocateBuffer(p_aout->sys->audioQueue, FRAME_SIZE * 2, &inBuffer);
156 if (status != noErr) {
157 msg_Err(p_aout, "buffer alloction failed (%i)", status);
161 memcpy(inBuffer->mAudioData, p_block->p_buffer, p_block->i_buffer);
162 inBuffer->mAudioDataByteSize = p_block->i_buffer;
163 block_Release(p_block);
165 status = AudioQueueEnqueueBuffer(p_aout->sys->audioQueue, inBuffer, 0, NULL);
167 msg_Err(p_aout, "enqueuing buffer failed (%i)", status);
171 void AudioQueueCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
172 /* this function does nothing, but needs to be here to make the AudioQueue API happy.
173 * without a callback, it will refuse to create an AudioQueue instance. */
174 VLC_UNUSED(inUserData);
176 VLC_UNUSED(inBuffer);
179 static void Pause (audio_output_t *p_aout, bool pause, mtime_t date)
184 AudioQueuePause(p_aout->sys->audioQueue);
186 AudioQueueStart(p_aout->sys->audioQueue, NULL);
189 static void Flush (audio_output_t *p_aout, bool wait)
191 if (p_aout->sys->b_stopped || !p_aout->sys->audioQueue)
195 AudioQueueFlush(p_aout->sys->audioQueue);
197 AudioQueueReset(p_aout->sys->audioQueue);
200 static int TimeGet (audio_output_t *p_aout, mtime_t *restrict delay)
210 /*****************************************************************************
212 *****************************************************************************/
214 static int Open(vlc_object_t *obj)
216 audio_output_t *aout = (audio_output_t *)obj;
217 aout_sys_t *sys = malloc(sizeof (*sys));
219 if (unlikely(sys == NULL))
229 static void Close(vlc_object_t *obj)
231 audio_output_t *aout = (audio_output_t *)obj;
232 msg_Dbg( aout, "audioqueue: Close");
233 aout_sys_t *sys = aout->sys;