]> git.sesse.net Git - vlc/blob - modules/gui/beos/AudioOutput.cpp
aout3 API change :
[vlc] / modules / gui / beos / AudioOutput.cpp
1 /*****************************************************************************
2  * aout.cpp: BeOS audio output
3  *****************************************************************************
4  * Copyright (C) 1999, 2000, 2001 VideoLAN
5  * $Id: AudioOutput.cpp,v 1.7 2002/08/30 23:27:06 massiot Exp $
6  *
7  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
8  *          Samuel Hocevar <sam@zoy.org>
9  *
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.
14  * 
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.
19  *
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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>                                      /* malloc(), free() */
30 #include <kernel/OS.h>
31 #include <View.h>
32 #include <Application.h>
33 #include <Message.h>
34 #include <Locker.h>
35 #include <media/MediaDefs.h>
36 #include <game/PushGameSound.h>
37 #include <malloc.h>
38 #include <string.h>
39
40 #include <vlc/vlc.h>
41 #include <vlc/aout.h>
42 #include "aout_internal.h"
43
44 /*****************************************************************************
45  * aout_sys_t: BeOS audio output method descriptor
46  *****************************************************************************
47  * This structure is part of the audio output thread descriptor.
48  * It describes some BeOS specific variables.
49  *****************************************************************************/
50 struct aout_sys_t
51 {
52     BPushGameSound   * p_sound;
53     gs_audio_format  * p_format;
54     void             * p_buffer;
55     int                  i_buffer_size;
56     uint             i_buffer_pos;
57     mtime_t          clock_diff;
58 };
59
60 #define FRAME_SIZE 2048
61
62 /*****************************************************************************
63  * Local prototypes.
64  *****************************************************************************/
65 static int  SetFormat    ( aout_instance_t * );
66 static void Play         ( aout_instance_t * );
67 static int  BeOSThread   ( aout_instance_t * );
68
69 /*****************************************************************************
70  * OpenAudio: opens a BPushGameSound
71  *****************************************************************************/
72 int E_(OpenAudio) ( vlc_object_t * p_this )
73 {       
74     aout_instance_t * p_aout = (aout_instance_t *)p_this;
75     struct aout_sys_t * p_sys;
76
77     /* Allocate structure */
78     p_aout->output.p_sys = p_sys = (aout_sys_t *)malloc( sizeof( struct aout_sys_t ) );
79     memset( p_sys, 0, sizeof( struct aout_sys_t ) );
80     if( p_sys == NULL )
81     {
82         msg_Err( p_aout, "out of memory" );
83         return -1;
84     }
85     
86     /* Initialize format */
87     p_sys->p_format = (gs_audio_format *)malloc( sizeof( struct gs_audio_format));
88     SetFormat(p_aout);
89
90     /* Allocate BPushGameSound */
91     p_sys->p_sound = new BPushGameSound( 8192,
92                                          p_sys->p_format,
93                                          2, NULL );
94     if( p_sys->p_sound->InitCheck() != B_OK )
95     {
96         free( p_sys->p_format );
97         free( p_sys );
98         msg_Err( p_aout, "cannot initialize BPushGameSound" );
99         return -1;
100     }
101
102     if( vlc_thread_create( p_aout, "aout", BeOSThread,
103                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
104     {
105         msg_Err( p_aout, "cannot create aout thread" );
106         delete p_sys->p_sound;
107         free( p_sys->p_format );
108         free( p_sys );
109         return -1;
110     }
111     
112     p_aout->output.pf_play = Play;
113
114     return 0;
115 }
116
117 /*****************************************************************************
118  * SetFormat: sets the dsp output format
119  *****************************************************************************/
120 static int SetFormat( aout_instance_t *p_aout )
121 {
122     /* Initialize some variables */
123     p_aout->output.p_sys->p_format->frame_rate = p_aout->output.output.i_rate;
124     p_aout->output.p_sys->p_format->channel_count = p_aout->output.output.i_channels;
125     
126     switch (p_aout->output.output.i_format)
127     {
128     case AOUT_FMT_S16_LE:
129         p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_S16;
130         p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
131         break;
132     case AOUT_FMT_S16_BE:
133         p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_S16;
134         p_aout->output.p_sys->p_format->byte_order = B_MEDIA_BIG_ENDIAN;
135         break;
136     case AOUT_FMT_S8:
137         p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_U8;
138         p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
139         break;
140     case AOUT_FMT_FLOAT32:
141         p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_F;
142         p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
143         break;
144     default:
145         msg_Err( p_aout, "cannot set audio format (%i)",
146                           p_aout->output.output.i_format );
147         return -1;
148     }
149
150     p_aout->output.p_sys->p_format->buffer_size = 4*8192;
151
152     return( 0 );
153 }
154
155 /*****************************************************************************
156  * Play: nothing to do
157  *****************************************************************************/
158 static void Play( aout_instance_t *p_aout )
159 {
160 }
161
162 /*****************************************************************************
163  * CloseAudio: closes the dsp audio device
164  *****************************************************************************/
165 void E_(CloseAudio) ( vlc_object_t *p_this )
166 {       
167     aout_instance_t * p_aout = (aout_instance_t *)p_this;
168
169     p_aout->output.p_sys->p_sound->UnlockCyclic();
170     p_aout->output.p_sys->p_sound->StopPlaying( );
171     delete p_aout->output.p_sys->p_sound;
172     
173     p_aout->b_die = 1;
174     free( p_aout->output.p_sys->p_format );
175     free( p_aout->output.p_sys );
176 }
177
178 /*****************************************************************************
179  * GetBufInfo: buffer status query
180  *****************************************************************************
181  * This function fills in the audio_buf_info structure :
182  * - returns : number of available fragments (not partially used ones)
183  * - int fragstotal : total number of fragments allocated
184  * - int fragsize : size of a fragment in bytes
185  * - int bytes : available space in bytes (includes partially used fragments)
186  * Note! 'bytes' could be more than fragments*fragsize
187  *****************************************************************************/
188 static int GetBufInfo( aout_instance_t * p_aout )
189 {
190     /* returns the allocated space in bytes */
191     return ( p_aout->output.p_sys->p_format->buffer_size );
192 }
193
194 /*****************************************************************************
195  * BeOSThread: asynchronous thread used to DMA the data to the device
196  *****************************************************************************/
197 static int BeOSThread( aout_instance_t * p_aout )
198 {
199     struct aout_sys_t * p_sys = p_aout->output.p_sys;
200
201     static uint i_buffer_pos;
202
203     p_sys->p_sound->StartPlaying( );
204     p_sys->p_sound->LockForCyclic( &p_sys->p_buffer,
205                                    (size_t *)&p_sys->i_buffer_size );
206
207     while ( !p_aout->b_die )
208     {
209         aout_buffer_t * p_buffer;
210         int i_tmp, i_size;
211         byte_t * p_bytes;
212
213         mtime_t next_date = 0;
214         /* Get the presentation date of the next write() operation. It
215          * is equal to the current date + duration of buffered samples.
216          * Order is important here, since GetBufInfo is believed to take
217          * more time than mdate(). */
218         next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
219                   / p_aout->output.output.i_bytes_per_frame
220                   / p_aout->output.output.i_rate
221                   * p_aout->output.output.i_frame_length;
222         next_date += mdate();
223
224         p_buffer = aout_OutputNextBuffer( p_aout, next_date, VLC_FALSE );
225  
226         int i_newbuf_pos;
227         if ( p_buffer != NULL )
228         {
229             p_bytes = p_buffer->p_buffer;
230             i_size = p_buffer->i_nb_bytes;
231         }
232         else
233         {
234             i_size = FRAME_SIZE / p_aout->output.output.i_frame_length
235                       * p_aout->output.output.i_bytes_per_frame;
236             p_bytes = (byte_t *)malloc( i_size );
237             memset( p_bytes, 0, i_size );
238         }
239    
240         if( (i_newbuf_pos = i_buffer_pos + p_buffer->i_size)
241                             > p_aout->output.p_sys->i_buffer_size )
242         {
243             p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer
244                             + i_buffer_pos),
245                               p_buffer->p_buffer,
246                               p_aout->output.p_sys->i_buffer_size - i_buffer_pos );
247
248             p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer),
249                             p_buffer->p_buffer + p_aout->output.p_sys->i_buffer_size - i_buffer_pos,
250                             p_buffer->i_size - ( p_aout->output.p_sys->i_buffer_size - i_buffer_pos ) );
251         
252             i_buffer_pos = i_newbuf_pos - i_buffer_pos;
253         }
254         else
255         {
256            p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer + i_buffer_pos),
257                     p_buffer->p_buffer, p_buffer->i_size );
258
259            i_buffer_pos = i_newbuf_pos;
260         }
261     }
262     
263     return 0;
264
265 }
266