Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

oss.c File Reference

#include <libdv/dv_types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#include "oss.h"

Include dependency graph for oss.c:

Go to the source code of this file.

Functions

kino_sound_tkino_sound_new (void)
int kino_sound_init (dv_audio_t *audio, kino_sound_t *sound, char const *device)
int kino_sound_player (kino_sound_t *sound, void *data, int size)
int kino_sound_play (dv_audio_t *audio, kino_sound_t *sound, int16_t **out)
void kino_sound_close (kino_sound_t *sound)


Function Documentation

void kino_sound_close kino_sound_t sound  ) 
 

Definition at line 400 of file oss.c.

Referenced by PageMagick::AudioThread(), and FrameDisplayer::CloseSound().

00401 {
00402     if ( sound != NULL )
00403     {
00404         if ( sound->fd != -1 )
00405             close( sound->fd );
00406         if ( sound->buffer )
00407             free( sound->buffer );
00408 #ifdef HAVE_ALSA
00409         if ( sound->pcmh )
00410             snd_pcm_close( sound->pcmh );
00411         if ( sound->hwparams )
00412             free( sound->hwparams );
00413 #endif
00414         free( sound );
00415     }
00416 }

int kino_sound_init dv_audio_t *  audio,
kino_sound_t sound,
char const *  device
 

Definition at line 63 of file oss.c.

References kino_sound_t::buffer, DV_AUDIO_MAX_SAMPLES, and kino_sound_t::fd.

Referenced by PageMagick::PlayAudio(), and FrameDisplayer::PutSound().

00064 {
00065     int rate_request, channels_request, fragment_request;
00066     int used = audio->frequency;
00067 
00068     channels_request = audio->num_channels;
00069     rate_request = audio->frequency;
00070     fragment_request = 0x0004000B;
00071     sound->buffer = NULL;
00072 
00073     if ( channels_request == 0 || rate_request == 0 )
00074         return FALSE;
00075 
00076     if ( !device || !*device )
00077         device = "plughw:0,0";
00078 
00079     /* open audio device
00080        Open nonblocking first, to test if available. */
00081     sound->fd = open( device, O_WRONLY | O_NONBLOCK | O_NDELAY );
00082     if ( sound->fd != -1 )
00083     {
00084         close( sound->fd );
00085         sound->fd = open( device, O_WRONLY );
00086     }
00087     if ( sound->fd != -1 )
00088     {
00089         /* OSS */
00090         int format = AFMT_S16_NE;
00091         int error = 0;
00092         if ( ioctl( sound->fd, SNDCTL_DSP_SETFRAGMENT, &fragment_request ) == -1 )
00093         {
00094             perror( "SNDCTL_DSP_SETFMT" );
00095             error = 1;
00096         }
00097         if ( error == 0 && ioctl( sound->fd, SOUND_PCM_WRITE_BITS, &format ) == -1 )
00098         {
00099             perror( "SNDCTL_DSP_SETFMT" );
00100             error = 2;
00101         }
00102         if ( error == 0 && format != AFMT_S16_NE )
00103         {
00104             fprintf( stderr, "soundcard doesn't support format\n" );
00105             error = 3;
00106         }
00107         if ( error == 0 && ioctl( sound->fd, SOUND_PCM_WRITE_CHANNELS, &channels_request ) )
00108         {
00109             fprintf( stderr, "soundcard doesn't support %d channels\n", audio->num_channels );
00110             error = 4;
00111         }
00112         if ( error == 0 && channels_request != audio->num_channels )
00113         {
00114             fprintf( stderr, "soundcard doesn't support %d channels\n", audio->num_channels );
00115             error = 5;
00116         }
00117         if ( error == 0 && ioctl( sound->fd, SOUND_PCM_WRITE_RATE, &rate_request ) == -1 )
00118         {
00119             perror( "SNDCTL_DSP_SPEED" );
00120             error = 6;
00121         }
00122         if ( error == 0 && rate_request != audio->frequency )
00123         {
00124             perror( "SNDCTL_DSP_SPEED" );
00125             error = 7;
00126         }
00127 
00128         if ( error == 6 || error == 7 )
00129         {
00130             rate_request = 44100;
00131             used = rate_request;
00132             fprintf( stderr, ">>> audio at %d failed - forcing resample at %dhz\n", audio->frequency, rate_request );
00133             if ( ioctl( sound->fd, SOUND_PCM_WRITE_RATE, &rate_request ) == -1 )
00134             {
00135                 perror( "SNDCTL_DSP_SPEED 44.1" );
00136                 used = 0;
00137                 error = 6;
00138             }
00139             else
00140             {
00141                 error = 0;
00142             }
00143             if ( error == 0 && rate_request != 44100 )
00144             {
00145                 perror( "SNDCTL_DSP_SPEED" );
00146                 error = 7;
00147                 used = 0;
00148             }
00149         }
00150 
00151         if ( error == 0 )
00152         {
00153             sound->buffer = malloc( DV_AUDIO_MAX_SAMPLES * audio->num_channels * sizeof( int16_t ) );
00154             if ( sound->buffer == NULL )
00155             {
00156                 fprintf( stderr, "Unable to allocate memory for the buffer\n" );
00157                 error = 8;
00158             }
00159         }
00160 
00161         if ( error != 0 )
00162         {
00163             close( sound->fd );
00164             sound->fd = -1;
00165             used = 0;
00166         }
00167     }
00168 #ifdef HAVE_ALSA
00169     else
00170     {
00171         /* ALSA */
00172         int serr;
00173         int error;
00174     
00175         sound->hwparams = NULL;
00176         sound->writefail_noted = 0;
00177     
00178         if ( channels_request == 0 || rate_request == 0 )
00179             return FALSE;
00180     
00181         sound->channels = audio->num_channels;
00182     
00183         if ((serr = snd_pcm_open(&sound->pcmh, device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0)
00184         {
00185             fprintf(stderr, "Could not open ALSA device \"%s\": %s\n", device ? device : "(default)", snd_strerror(serr));
00186             return FALSE;
00187         }
00188     
00189         snd_pcm_nonblock(sound->pcmh, 0);
00190     
00191         error = 0;
00192     
00193         if ((serr = snd_pcm_hw_params_malloc(&sound->hwparams)) < 0)
00194         {
00195             fprintf(stderr, "Could not allocate ALSA hardware parameters: %s\n", snd_strerror(serr));
00196             error = 8;
00197         }
00198     
00199         if (!error &&
00200             (serr = snd_pcm_hw_params_any(sound->pcmh, sound->hwparams)) < 0)
00201         {
00202             fprintf(stderr, "Could not get ALSA hardware parameters: %s\n", snd_strerror(serr));
00203             error = 1;
00204         }
00205         if (!error &&
00206             (serr = snd_pcm_hw_params_set_access(sound->pcmh, sound->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
00207         {
00208             fprintf(stderr, "Could not set ALSA interleaved access: %s\n", snd_strerror(serr));
00209             error = 2;
00210         }
00211         if (!error &&
00212             (serr = snd_pcm_hw_params_set_format(sound->pcmh, sound->hwparams, SND_PCM_FORMAT_S16)) < 0)
00213         {
00214             fprintf(stderr, "Could not set ALSA sample format: %s\n", snd_strerror(serr));
00215             error = 2;
00216         }
00217         if (!error &&
00218             (serr = snd_pcm_hw_params_set_channels(sound->pcmh, sound->hwparams, channels_request)) < 0)
00219         {
00220             fprintf(stderr, "Could not set ALSA channels to %d: %s\n", channels_request, snd_strerror(serr));
00221             error = 4;
00222         }
00223         if (!error &&
00224             (serr = snd_pcm_hw_params_set_rate_resample(sound->pcmh, sound->hwparams, 1)) < 0)
00225         {
00226             fprintf(stderr, "Could not set ALSA resampling: %s\n", snd_strerror(serr));
00227             error = 7;
00228         }
00229     
00230         if (!error &&
00231             (serr = snd_pcm_hw_params_set_rate_near(sound->pcmh, sound->hwparams, ( unsigned* )&rate_request, 0)) < 0)
00232         {
00233             fprintf(stderr, "Could not set ALSA rate to %d: %s\n", rate_request, snd_strerror(serr));
00234             error = 6;
00235         }
00236     
00237         if (!error &&
00238             (serr = snd_pcm_hw_params(sound->pcmh, sound->hwparams)) < 0)
00239         {
00240             fprintf(stderr, "Could not set ALSA Hardware parameters %s\n", snd_strerror(serr));
00241             error = 9;
00242         }
00243     
00244         if (!error)
00245         {
00246             sound->buffer = malloc( DV_AUDIO_MAX_SAMPLES * audio->num_channels * sizeof( int16_t ) );
00247             if ( sound->buffer == NULL )
00248             {
00249                 fprintf( stderr, "Unable to allocate memory for the buffer\n" );
00250                 error = 8;
00251             }
00252         }
00253     
00254         if (error)
00255         {
00256             fprintf( stderr, "Unable to open audio device %s\n", device );
00257             snd_pcm_close(sound->pcmh);
00258             if (sound->hwparams)
00259                 free(sound->hwparams);
00260             sound->pcmh = 0;
00261             used = 0;
00262         }
00263     }
00264 #endif
00265     return used;
00266 }

kino_sound_t* kino_sound_new void   ) 
 

Definition at line 45 of file oss.c.

References kino_sound_t::fd.

Referenced by PageMagick::AudioThread(), and FrameDisplayer::PutSound().

00046 {
00047     kino_sound_t * result;
00048 
00049     result = ( kino_sound_t * ) calloc( 1, sizeof( kino_sound_t ) );
00050     if ( result != NULL )
00051     {
00052         result->fd = -1;
00053     }
00054 
00055     return result;
00056 }

int kino_sound_play dv_audio_t *  audio,
kino_sound_t sound,
int16_t **  out
 

Definition at line 322 of file oss.c.

References kino_sound_t::arg_audio_file, kino_sound_t::buffer, and kino_sound_t::fd.

Referenced by PageMagick::PlayAudio().

00323 {
00324     int ch, i, j = 0, total, written = 0, result;
00325 
00326     /* Interleave the audio into a single buffer */
00327     for ( i = 0; i < audio->samples_this_frame; i++ )
00328     {
00329         for ( ch = 0; ch < audio->num_channels; ch++ )
00330         {
00331             sound->buffer[ j++ ] = out[ ch ][ i ];
00332         }
00333     }
00334 
00335     if ( sound->fd > -1 )
00336     {
00337         /* OSS */
00338         total = audio->samples_this_frame * audio->num_channels * sizeof( int16_t );
00339         do
00340         {
00341             result = write( sound->fd, sound->buffer, total );
00342             if ( result != total )
00343                 goto write_error;
00344             written += result;
00345         }
00346         while ( total > written );
00347         if ( !sound->arg_audio_file )
00348         {
00349             if ( ioctl( sound->fd, SNDCTL_DSP_POST, NULL ) == -1 )
00350                 goto post_ioctl;
00351         } /* if */
00352     
00353         return ( TRUE );
00354     
00355 write_error:
00356         perror( "write" );
00357         return ( FALSE );
00358 
00359 post_ioctl:
00360         perror( "SNDCTL_DSP_POST" );
00361         return ( FALSE );
00362     }
00363 #ifdef HAVE_ALSA
00364     else
00365     {
00366         /* ALSA */
00367         total = audio->samples_this_frame;
00368         do
00369         {
00370             result = snd_pcm_writei( sound->pcmh, sound->buffer + written * audio->num_channels, total - written );
00371             if ( result == -EAGAIN )
00372             {
00373                 snd_pcm_wait( sound->pcmh, 1000 );
00374                 result = snd_pcm_writei( sound->pcmh, sound->buffer + written * audio->num_channels, total - written );
00375             }
00376             else if ( result == -EPIPE )
00377             {
00378                 snd_pcm_prepare( sound->pcmh );
00379                 result = snd_pcm_writei( sound->pcmh, sound->buffer + written * audio->num_channels, total - written );
00380             }
00381             if (result < 0)
00382             {
00383                 if (!sound->writefail_noted)
00384                 {
00385                     sound->writefail_noted = 1;
00386                     fprintf( stderr, "Could not write to ALSA: %s\n", snd_strerror ( result ) );
00387                 }
00388                 return FALSE;
00389             }
00390             written += result;
00391         }
00392         while ( total > written );
00393     
00394         return ( TRUE );
00395     }
00396 #endif
00397 }

int kino_sound_player kino_sound_t sound,
void *  data,
int  size
 

Definition at line 269 of file oss.c.

References kino_sound_t::fd.

Referenced by FrameDisplayer::PutSound().

00270 {
00271     if ( sound->fd > -1 )
00272     {
00273         /* OSS */
00274         return write( sound->fd, data, size ) == size;
00275     }
00276 #ifdef HAVE_ALSA
00277     else
00278     {
00279         /* ALSA */
00280         int frames = size / sound->channels / sizeof(int16_t);
00281         int result;
00282         int16_t *framedata = data;
00283     
00284         while (frames > 0)
00285         {
00286             result = snd_pcm_writei( sound->pcmh, framedata, frames );
00287             if ( result == -EAGAIN )
00288             {
00289                 snd_pcm_wait( sound->pcmh, 1000 );
00290                 result = snd_pcm_writei( sound->pcmh, framedata, frames );
00291             }
00292             else if ( result == -EPIPE )
00293             {
00294                 snd_pcm_prepare( sound->pcmh );
00295                 result = snd_pcm_writei( sound->pcmh, framedata, frames );
00296             }
00297             if (result < 0)
00298             {
00299                 if (!sound->writefail_noted)
00300                 {
00301                     sound->writefail_noted = 1;
00302                     fprintf( stderr, "Could not write to ALSA: %s\n", snd_strerror ( result ) );
00303                 }
00304                 return FALSE;
00305             }
00306             framedata += result * sound->channels;
00307             frames -= result;
00308         }
00309         if ( framedata != ( int16_t* )( (char *) data + size ) )
00310         {
00311             fprintf(stderr, "Misaligned after write to ALSA: should be at %p, but we are at %p\n",
00312                     (char *) data + size,
00313                     framedata);
00314         }
00315         return TRUE;
00316     }
00317 #endif
00318     return FALSE;
00319 }


Generated on Sun Mar 11 22:12:13 2007 for Kino by  doxygen 1.4.2