Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

hd1000a.cpp

00001 /*****************************************************************************
00002  * hd1000a.cpp : Roku HD1000 audio output
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: hd1000a.cpp 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Author: Jon Lech Johansen <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00024 /*****************************************************************************
00025  * Preamble
00026  *****************************************************************************/
00027 extern "C"
00028 {
00029 #include <string.h>
00030 #include <stdlib.h>
00031 #include <errno.h>
00032 
00033 #include <vlc/vlc.h>
00034 #include <vlc/aout.h>
00035 
00036 #include "aout_internal.h"
00037 }
00038 
00039 #include <deschutes/libraries/hdmachinex225/PCMAudioPlayer.h>
00040 
00041 #define FRAME_SIZE 4096
00042 
00043 /*****************************************************************************
00044  * aout_sys_t: audio output method descriptor
00045  *****************************************************************************
00046  * This structure is part of the audio output thread descriptor.
00047  * It describes the direct sound specific properties of an audio device.
00048  *****************************************************************************/
00049 struct aout_sys_t
00050 {
00051     u32 nAlignment;
00052     u32 nSizeMultiple;
00053     u32 nBuffers;
00054     u32 nBufferSize;
00055     void ** ppBuffers;
00056     u32 nNextBufferIndex;
00057     PCMAudioPlayer * pPlayer;
00058 };
00059 
00060 /*****************************************************************************
00061  * Local prototypes.
00062  *****************************************************************************/
00063 static int     Open        ( vlc_object_t * );
00064 static void    Close       ( vlc_object_t * );
00065 
00066 static void    Play        ( aout_instance_t * );
00067 static int     Thread      ( aout_instance_t * );
00068 
00069 static void    InterleaveS16( int16_t *, int16_t * );
00070 
00071 /*****************************************************************************
00072  * Module descriptor
00073  *****************************************************************************/
00074 vlc_module_begin();
00075     set_shortname( "Roku HD1000" );
00076     set_description( N_("Roku HD1000 audio output") );
00077     set_capability( "audio output", 100 );
00078     set_category( CAT_AUDIO );
00079     set_subcategory( SUBCAT_AUDIO_AOUT );
00080     set_callbacks( Open, Close );
00081 vlc_module_end();
00082 
00083 /*****************************************************************************
00084  * Open: open a dummy audio device
00085  *****************************************************************************/
00086 static int Open( vlc_object_t * p_this )
00087 {
00088     aout_instance_t * p_aout = (aout_instance_t *)p_this;
00089     struct aout_sys_t * p_sys;
00090     PCMAudioPlayer * pPlayer;
00091     int i_volume;
00092 
00093     /* Allocate structure */
00094     p_aout->output.p_sys = p_sys =
00095         (aout_sys_t *)malloc( sizeof( aout_sys_t ) );
00096     if( p_aout->output.p_sys == NULL )
00097     {
00098         msg_Err( p_aout, "out of memory" );
00099         return VLC_EGENERIC;
00100     }
00101 
00102     /* New PCMAudioPlayer */
00103     p_sys->pPlayer = pPlayer = new PCMAudioPlayer();
00104     if( p_sys->pPlayer == NULL )
00105     {
00106         msg_Err( p_aout, "out of memory" );
00107         free( p_sys );
00108         return VLC_EGENERIC;
00109     }
00110 
00111     /* Get Buffer Requirements */
00112     if( !pPlayer->GetBufferRequirements( p_sys->nAlignment,
00113                                          p_sys->nSizeMultiple,
00114                                          p_sys->nBuffers ) )
00115     {
00116         msg_Err( p_aout, "GetBufferRequirements failed" );
00117         delete pPlayer;
00118         free( p_sys );
00119         return VLC_EGENERIC;
00120     } 
00121 
00122     p_sys->nBuffers = __MIN( p_sys->nBuffers, 4 );
00123 
00124     p_sys->ppBuffers = (void **)malloc( p_sys->nBuffers * sizeof( void * ) );
00125     if( p_sys->ppBuffers == NULL )
00126     {
00127         msg_Err( p_aout, "out of memory" );
00128         delete pPlayer;
00129         free( p_sys );
00130         return VLC_EGENERIC;
00131     }
00132 
00133     /* Open PCMAudioPlayer */
00134     p_sys->nBufferSize = FRAME_SIZE * 4;
00135     if( !pPlayer->Open( p_sys->nBuffers, p_sys->nBufferSize,
00136                         p_sys->ppBuffers ) )
00137     {
00138         msg_Err( p_aout, "Open failed" );
00139         delete pPlayer;
00140         free( p_sys->ppBuffers );
00141         free( p_sys );
00142         return VLC_EGENERIC;
00143     }
00144 
00145     p_sys->nNextBufferIndex = 0;
00146 
00147     if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
00148     {
00149         p_aout->output.output.i_rate = 44100;
00150         if( !pPlayer->SetSampleRate( p_aout->output.output.i_rate ) )
00151         {
00152             msg_Err( p_aout, "SetSampleRate failed" );
00153             pPlayer->Close();
00154             delete pPlayer;
00155             free( p_sys->ppBuffers );
00156             free( p_sys );
00157             return VLC_EGENERIC;
00158         }
00159     }
00160 
00161     p_aout->output.output.i_format = AOUT_FMT_S16_NE;
00162     p_aout->output.i_nb_samples = FRAME_SIZE;
00163     p_aout->output.output.i_physical_channels
00164             = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
00165     p_aout->output.pf_play = Play;
00166     aout_VolumeSoftInit( p_aout );
00167 
00168     i_volume = config_GetInt( p_aout->p_vlc, "volume" );
00169     pPlayer->SetVolume( (u32)__MIN( i_volume * 64, 0xFFFF ) );
00170 
00171     /* Create thread and wait for its readiness. */
00172     if( vlc_thread_create( p_aout, "aout", Thread,
00173                            VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
00174     {
00175         msg_Err( p_aout, "cannot create OSS thread (%s)", strerror(errno) );
00176         pPlayer->Close();
00177         delete pPlayer;
00178         free( p_sys->ppBuffers );
00179         free( p_sys );
00180         return VLC_ETHREAD;
00181     }
00182 
00183     return VLC_SUCCESS;
00184 }
00185 
00186 /*****************************************************************************
00187  * Close: close our file
00188  *****************************************************************************/
00189 static void Close( vlc_object_t * p_this )
00190 {
00191     u32 i;
00192     aout_instance_t * p_aout = (aout_instance_t *)p_this;
00193     struct aout_sys_t * p_sys = p_aout->output.p_sys;
00194 
00195     p_aout->b_die = VLC_TRUE;
00196     vlc_thread_join( p_aout );
00197     p_aout->b_die = VLC_FALSE;
00198 
00199     do
00200     {
00201         i = p_sys->pPlayer->WaitForBuffer();
00202     } while( i != 0 && i != p_sys->nBuffers );
00203 
00204     p_sys->pPlayer->Close();
00205     delete p_sys->pPlayer;
00206 
00207     free( p_sys->ppBuffers );
00208     free( p_sys );
00209 }
00210 
00211 /*****************************************************************************
00212  * Play: do nothing
00213  *****************************************************************************/
00214 static void Play( aout_instance_t * p_aout )
00215 {
00216 }
00217 
00218 /*****************************************************************************
00219  * Thread: thread used to DMA the data to the device
00220  *****************************************************************************/
00221 static int Thread( aout_instance_t * p_aout )
00222 {
00223     aout_buffer_t * p_buffer;
00224     struct aout_sys_t * p_sys = p_aout->output.p_sys;
00225     PCMAudioPlayer * pPlayer = p_sys->pPlayer;
00226 
00227     while( !p_aout->b_die )
00228     {
00229         pPlayer->WaitForBuffer();
00230 
00231         vlc_mutex_lock( &p_aout->output_fifo_lock );
00232         p_buffer = aout_FifoPop( p_aout, &p_aout->output.fifo );
00233         vlc_mutex_unlock( &p_aout->output_fifo_lock );
00234 
00235 #define i p_sys->nNextBufferIndex
00236         if( p_buffer == NULL )
00237         {
00238             p_aout->p_vlc->pf_memset( p_sys->ppBuffers[ i ], 0,
00239                                       p_sys->nBufferSize ); 
00240         }
00241         else
00242         {
00243             InterleaveS16( (int16_t *)p_buffer->p_buffer,
00244                            (int16_t *)p_sys->ppBuffers[ i ] );
00245             aout_BufferFree( p_buffer );
00246         }
00247 
00248         if( !pPlayer->QueueBuffer( (s16 *)p_sys->ppBuffers[ i ],
00249                                    p_sys->nBufferSize / 2 ) )
00250         {
00251             msg_Err( p_aout, "QueueBuffer failed" );
00252         } 
00253 
00254         i = (i + 1) % p_sys->nBuffers;
00255 #undef i
00256     }
00257 
00258     return VLC_SUCCESS;
00259 }
00260 
00261 /*****************************************************************************
00262  * InterleaveS16: interleave samples
00263  *****************************************************************************/
00264 static void InterleaveS16( int16_t * p_in, int16_t * p_out )
00265 {
00266     for( int i = 0; i < FRAME_SIZE; i++ )
00267     {
00268         p_out[ i * 2 + 0 ] = p_in[ i * 2 + 1 ];
00269         p_out[ i * 2 + 1 ] = p_in[ i * 2 + 0 ];
00270     }
00271 }

Generated on Tue Dec 20 10:14:28 2005 for vlc-0.8.4a by  doxygen 1.4.2