Rewritten aout3. BeOS currently PUSHES the audio.
authorTony Castley <tcastley@videolan.org>
Fri, 23 Aug 2002 14:16:23 +0000 (14:16 +0000)
committerTony Castley <tcastley@videolan.org>
Fri, 23 Aug 2002 14:16:23 +0000 (14:16 +0000)
modules/gui/beos/AudioOutput.cpp

index cb58831..a98fed7 100644 (file)
@@ -2,7 +2,7 @@
  * aout.cpp: BeOS audio output
  *****************************************************************************
  * Copyright (C) 1999, 2000, 2001 VideoLAN
- * $Id: AudioOutput.cpp,v 1.4 2002/08/19 21:54:37 massiot Exp $
+ * $Id: AudioOutput.cpp,v 1.5 2002/08/23 14:16:23 tcastley Exp $
  *
  * Authors: Jean-Marc Dressler <polux@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -53,17 +53,23 @@ struct aout_sys_t
     gs_audio_format  * p_format;
     void             * p_buffer;
     int                 i_buffer_size;
-    int              i_buffer_pos;
+    uint             i_buffer_pos;
+    volatile vlc_bool_t   b_initialized;
     mtime_t          clock_diff;
 
 };
 
+#define FRAME_SIZE 2048
+
 /*****************************************************************************
  * Local prototypes.
  *****************************************************************************/
-static int     SetFormat   ( aout_instance_t * );
-//static int     GetBufInfo  ( aout_instance_t *, int );
-static void    Play        ( aout_instance_t * );
+int  Open         ( vlc_object_t * );
+void Close        ( vlc_object_t * );
+
+static int  SetFormat    ( aout_instance_t * );
+static void Play         ( aout_instance_t * );
+static int  BeOSThread    ( aout_instance_t * );
 
 /*****************************************************************************
  * OpenAudio: opens a BPushGameSound
@@ -74,45 +80,45 @@ int E_(OpenAudio) ( vlc_object_t * p_this )
     aout_instance_t * p_aout = (aout_instance_t *)p_this;
     struct aout_sys_t * p_sys;
 
-    /* Allocate instance */
-    p_sys = p_aout->output.p_sys = (aout_sys_t *)malloc( sizeof( struct aout_sys_t ) );
+    /* Allocate structure */
+    p_aout->output.p_sys = p_sys = (aout_sys_t *)malloc( sizeof( struct aout_sys_t ) );
     memset( p_sys, 0, sizeof( struct aout_sys_t ) );
-    if( p_aout->output.p_sys == NULL )
+    if( p_sys == NULL )
     {
         msg_Err( p_aout, "out of memory" );
-        return( 1 );
+        return -1;
     }
-    p_aout->output.pf_setformat = SetFormat;
+    
+    /* Initialize format */
     p_sys->p_format = (gs_audio_format *)malloc( sizeof( struct gs_audio_format));
     SetFormat(p_aout);
+
     /* Allocate BPushGameSound */
     p_sys->p_sound = new BPushGameSound( 8192,
                                          p_sys->p_format,
                                          2, NULL );
-    if( p_sys->p_sound == NULL )
+    if( p_sys->p_sound->InitCheck() != B_OK )
     {
         free( p_sys->p_format );
         free( p_sys );
-        msg_Err( p_aout, "cannot allocate BPushGameSound" );
-        return( 1 );
+        msg_Err( p_aout, "cannot initialize BPushGameSound" );
+        return -1;
     }
 
-    if( p_sys->p_sound->InitCheck() != B_OK )
+    if( vlc_thread_create( p_aout, "aout", BeOSThread, VLC_FALSE) )
     {
+        msg_Err( p_aout, "cannot create OSS thread " );
+        delete p_sys->p_sound;
         free( p_sys->p_format );
         free( p_sys );
-        msg_Err( p_aout, "cannot initialize BPushGameSound" );
-        return( 1 );
-    }
-
-    p_sys->p_sound->StartPlaying( );
-
-    p_sys->p_sound->LockForCyclic( &p_sys->p_buffer,
-                                   (size_t *)&p_sys->i_buffer_size );
+        return -1;
 
+    }
+    
     p_aout->output.pf_setformat = SetFormat;
     p_aout->output.pf_play = Play;
-    return( 0 );
+
+    return 0;
 }
 
 /*****************************************************************************
@@ -123,13 +129,35 @@ static int SetFormat( aout_instance_t *p_aout )
     /* Initialize some variables */
     p_aout->output.p_sys->p_format->frame_rate = p_aout->output.output.i_rate;
     p_aout->output.p_sys->p_format->channel_count = p_aout->output.output.i_channels;
-    p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_S16;
-    p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
+    
+    switch (p_aout->output.output.i_format)
+    {
+    case AOUT_FMT_S16_LE:
+        p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_S16;
+        p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
+        break;
+    case AOUT_FMT_S16_BE:
+        p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_S16;
+        p_aout->output.p_sys->p_format->byte_order = B_MEDIA_BIG_ENDIAN;
+        break;
+    case AOUT_FMT_S8:
+        p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_U8;
+        p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
+        break;
+    case AOUT_FMT_FLOAT32:
+        p_aout->output.p_sys->p_format->format = gs_audio_format::B_GS_F;
+        p_aout->output.p_sys->p_format->byte_order = B_MEDIA_LITTLE_ENDIAN;
+        break;
+    default:
+        msg_Err( p_aout, "cannot set audio format (%i)",
+                          p_aout->output.output.i_format );
+        return -1;
+    }
+
     p_aout->output.p_sys->p_format->buffer_size = 4*8192;
-    p_aout->output.p_sys->i_buffer_pos = 0;
-    msg_Err( p_aout, "Rate: %d, Channels: %d", p_aout->output.output.i_rate, p_aout->output.output.i_channels);
 
-//    p_aout->output.pf_getbufinfo = GetBufInfo;
+    p_aout->output.p_sys->b_initialized = VLC_TRUE;
+
     return( 0 );
 }
 
@@ -140,32 +168,6 @@ static int SetFormat( aout_instance_t *p_aout )
  *****************************************************************************/
 static void Play( aout_instance_t *p_aout )
 {
-    aout_buffer_t * p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
-    int i_newbuf_pos;
-
-    if( (i_newbuf_pos = p_aout->output.p_sys->i_buffer_pos + p_buffer->i_size)
-              > p_aout->output.p_sys->i_buffer_size )
-    {
-        p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer
-                        + p_aout->output.p_sys->i_buffer_pos),
-                p_buffer->p_buffer,
-                p_aout->output.p_sys->i_buffer_size - p_aout->output.p_sys->i_buffer_pos );
-
-        p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer),
-                p_buffer->p_buffer + p_aout->output.p_sys->i_buffer_size - p_aout->output.p_sys->i_buffer_pos,
-                p_buffer->i_size - ( p_aout->output.p_sys->i_buffer_size
-                             - p_aout->output.p_sys->i_buffer_pos ) );
-        
-        p_aout->output.p_sys->i_buffer_pos = i_newbuf_pos - p_aout->output.p_sys->i_buffer_size;
-
-    }
-    else
-    {
-       p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer + p_aout->output.p_sys->i_buffer_pos),
-                p_buffer->p_buffer, p_buffer->i_size );
-
-       p_aout->output.p_sys->i_buffer_pos = i_newbuf_pos;
-    }
 }
 
 /*****************************************************************************
@@ -178,13 +180,102 @@ void E_(CloseAudio) ( vlc_object_t *p_this )
     p_aout->output.p_sys->p_sound->UnlockCyclic();
     p_aout->output.p_sys->p_sound->StopPlaying( );
     delete p_aout->output.p_sys->p_sound;
+    
+    p_aout->b_die = 1;
     free( p_aout->output.p_sys->p_format );
     free( p_aout->output.p_sys );
 }
 
 /*****************************************************************************
- * SDLCallback: what to do once SDL has played sound samples
+ * GetBufInfo: buffer status query
+ *****************************************************************************
+ * This function fills in the audio_buf_info structure :
+ * - returns : number of available fragments (not partially used ones)
+ * - int fragstotal : total number of fragments allocated
+ * - int fragsize : size of a fragment in bytes
+ * - int bytes : available space in bytes (includes partially used fragments)
+ * Note! 'bytes' could be more than fragments*fragsize
  *****************************************************************************/
-static void BeOSCallback( void * _p_aout, byte_t * p_stream, int i_len )
+static int GetBufInfo( aout_instance_t * p_aout )
 {
+    /* returns the allocated space in bytes */
+    return ( p_aout->output.p_sys->p_format->buffer_size );
 }
+
+/*****************************************************************************
+ * BeOSThread: asynchronous thread used to DMA the data to the device
+ *****************************************************************************/
+static int BeOSThread( aout_instance_t * p_aout )
+{
+    struct aout_sys_t * p_sys = p_aout->output.p_sys;
+
+    static uint i_buffer_pos;
+
+    p_sys->p_sound->StartPlaying( );
+    p_sys->p_sound->LockForCyclic( &p_sys->p_buffer,
+                                   (size_t *)&p_sys->i_buffer_size );
+
+    while ( !p_aout->b_die )
+    {
+        aout_buffer_t * p_buffer;
+        int i_tmp, i_size;
+        byte_t * p_bytes;
+
+        if( !p_sys->b_initialized )
+        {
+            msleep( THREAD_SLEEP );
+            continue;
+        }
+        mtime_t next_date = 0;
+        /* Get the presentation date of the next write() operation. It
+         * is equal to the current date + duration of buffered samples.
+         * Order is important here, since GetBufInfo is believed to take
+         * more time than mdate(). */
+        next_date = (mtime_t)GetBufInfo( p_aout ) * 1000000
+                  / p_aout->output.output.i_bytes_per_frame
+                  / p_aout->output.output.i_rate
+                  * p_aout->output.output.i_frame_length;
+        next_date += mdate();
+
+        p_buffer = aout_OutputNextBuffer( p_aout, next_date, VLC_FALSE );
+        int i_newbuf_pos;
+        if ( p_buffer != NULL )
+        {
+            p_bytes = p_buffer->p_buffer;
+            i_size = p_buffer->i_nb_bytes;
+        }
+        else
+        {
+            i_size = FRAME_SIZE / p_aout->output.output.i_frame_length
+                      * p_aout->output.output.i_bytes_per_frame;
+            p_bytes = (byte_t *)malloc( i_size );
+            memset( p_bytes, 0, i_size );
+        }
+   
+        if( (i_newbuf_pos = i_buffer_pos + p_buffer->i_size)
+                            > p_aout->output.p_sys->i_buffer_size )
+        {
+            p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer
+                            + i_buffer_pos),
+                              p_buffer->p_buffer,
+                              p_aout->output.p_sys->i_buffer_size - i_buffer_pos );
+
+            p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer),
+                            p_buffer->p_buffer + p_aout->output.p_sys->i_buffer_size - i_buffer_pos,
+                            p_buffer->i_size - ( p_aout->output.p_sys->i_buffer_size - i_buffer_pos ) );
+        
+            i_buffer_pos = i_newbuf_pos - i_buffer_pos;
+        }
+        else
+        {
+           p_aout->p_vlc->pf_memcpy( (void *)((int)p_aout->output.p_sys->p_buffer + i_buffer_pos),
+                    p_buffer->p_buffer, p_buffer->i_size );
+
+           i_buffer_pos = i_newbuf_pos;
+        }
+    }
+    
+    return 0;
+
+}
\ No newline at end of file