Search
lxdream.org :: lxdream/src/drivers/audio_alsa.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/audio_alsa.c
changeset 1073:92dfe34665ed
prev1024:c67f2d61ab97
author nkeynes
date Fri Sep 17 20:08:50 2010 +1000 (13 years ago)
permissions -rwxr-xr-x
last change Refactor shader management to support multiple programs, which are all
defined in the shaders.glsl, rather than split up into one file per
fragment.
file annotate diff log raw
bhaal22@643
     1
/**
nkeynes@1021
     2
 * $Id$
bhaal22@643
     3
 * 
bhaal22@643
     4
 * The asla  audio driver
bhaal22@643
     5
 *
bhaal22@643
     6
 * Copyright (c) 2008 Jonathan Muller
bhaal22@643
     7
 *
bhaal22@643
     8
 * This program is free software; you can redistribute it and/or modify
bhaal22@643
     9
 * it under the terms of the GNU General Public License as published by
bhaal22@643
    10
 * the Free Software Foundation; either version 2 of the License, or
bhaal22@643
    11
 * (at your option) any later version.
bhaal22@643
    12
 *
bhaal22@643
    13
 * This program is distributed in the hope that it will be useful,
bhaal22@643
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
bhaal22@643
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
bhaal22@643
    16
 * GNU General Public License for more details.
bhaal22@643
    17
 */
bhaal22@643
    18
#include <stdio.h>
bhaal22@643
    19
#include <unistd.h>
bhaal22@643
    20
bhaal22@643
    21
/* Use the newer ALSA API */
bhaal22@643
    22
#define ALSA_PCM_NEW_HW_PARAMS_API
bhaal22@643
    23
bhaal22@643
    24
#include <alsa/asoundlib.h>
bhaal22@643
    25
#include "config.h"
bhaal22@643
    26
#include "aica/audio.h"
bhaal22@643
    27
#include "dream.h"
bhaal22@643
    28
bhaal22@643
    29
bhaal22@643
    30
static snd_pcm_t *_soundDevice = NULL;
bhaal22@643
    31
static int frame_bytes;
bhaal22@643
    32
bhaal22@643
    33
nkeynes@1073
    34
static struct lxdream_config_group alsa_config = {
nkeynes@1073
    35
        "alsa", NULL, NULL, NULL,
nkeynes@1073
    36
        {{"device", N_("Audio output device"), CONFIG_TYPE_FILE, "default"},
nkeynes@1073
    37
        {NULL, CONFIG_TYPE_NONE}}  };
bhaal22@643
    38
bhaal22@643
    39
nkeynes@1024
    40
static gboolean audio_alsa_init(  )
bhaal22@643
    41
{
bhaal22@643
    42
    int err;
bhaal22@643
    43
    snd_pcm_hw_params_t *hw_params;
bhaal22@643
    44
    snd_pcm_sw_params_t *sw_params;
bhaal22@643
    45
    snd_pcm_uframes_t frames;
bhaal22@643
    46
    snd_pcm_uframes_t bufferSize;
nkeynes@806
    47
    unsigned int rate = DEFAULT_SAMPLE_RATE;
nkeynes@697
    48
    int format = DEFAULT_SAMPLE_FORMAT;
bhaal22@643
    49
    int dir;
bhaal22@643
    50
bhaal22@643
    51
bhaal22@643
    52
    // Open the device we were told to open.
nkeynes@1073
    53
    err = snd_pcm_open( &_soundDevice, alsa_config.params[0].value,
nkeynes@736
    54
            SND_PCM_STREAM_PLAYBACK, 0 );
bhaal22@643
    55
bhaal22@643
    56
    // Check for error on open.
bhaal22@643
    57
    if ( err < 0 ) {
bhaal22@643
    58
        ERROR( "Init: cannot open audio device %s (%s)\n",
nkeynes@1073
    59
                alsa_config.params[0].value, snd_strerror( err ) );
bhaal22@643
    60
        return FALSE;
bhaal22@643
    61
    } else {
bhaal22@643
    62
        DEBUG( "Audio device opened successfully." );
bhaal22@643
    63
    }
bhaal22@643
    64
bhaal22@643
    65
    frame_bytes = ( 2 * ( snd_pcm_format_width( SND_PCM_FORMAT_S16_LE ) / 8 ) );
bhaal22@643
    66
bhaal22@643
    67
bhaal22@643
    68
    //snd_pcm_hw_params_alloca (&hw_params);
bhaal22@643
    69
    // Allocate the hardware parameter structure.
bhaal22@643
    70
    if ( ( err = snd_pcm_hw_params_malloc( &hw_params ) ) < 0 ) {
bhaal22@643
    71
        ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
nkeynes@736
    72
                snd_strerror( err ) );
bhaal22@643
    73
        return FALSE;
bhaal22@643
    74
    }
bhaal22@643
    75
bhaal22@643
    76
    if ( ( err = snd_pcm_hw_params_any( _soundDevice, hw_params ) ) < 0 ) {
bhaal22@643
    77
        ERROR( "Init: cannot allocate hardware parameter structure (%s)\n",
nkeynes@736
    78
                snd_strerror( err ) );
bhaal22@643
    79
        return FALSE;
bhaal22@643
    80
    }
bhaal22@643
    81
    // Set access to RW interleaved.
bhaal22@643
    82
    if ( ( err = snd_pcm_hw_params_set_access( _soundDevice, hw_params,
nkeynes@736
    83
            SND_PCM_ACCESS_RW_INTERLEAVED ) )
nkeynes@736
    84
            < 0 ) {
bhaal22@643
    85
        ERROR( " Init: cannot set access type (%s)\n", snd_strerror( err ) );
bhaal22@643
    86
        return FALSE;
bhaal22@643
    87
    }
bhaal22@643
    88
bhaal22@643
    89
    if ( ( err = snd_pcm_hw_params_set_format( _soundDevice, hw_params,
nkeynes@736
    90
            SND_PCM_FORMAT_S16_LE ) ) <
nkeynes@736
    91
            0 ) {
bhaal22@643
    92
        ERROR( "Init: cannot set sample format (%s)\n", snd_strerror( err ) );
bhaal22@643
    93
        return FALSE;
bhaal22@643
    94
    }
bhaal22@643
    95
bhaal22@643
    96
    err = snd_pcm_hw_params_set_rate_near( _soundDevice, hw_params, &rate, 0 );
bhaal22@643
    97
    if ( err < 0 ) {
bhaal22@643
    98
        ERROR( "Init: Resampling setup failed for playback: %s\n",
nkeynes@736
    99
                snd_strerror( err ) );
bhaal22@643
   100
        return err;
bhaal22@643
   101
    }
bhaal22@643
   102
    // Set channels to stereo (2).
bhaal22@643
   103
    err = snd_pcm_hw_params_set_channels( _soundDevice, hw_params, 2 );
bhaal22@643
   104
    if ( err < 0 ) {
bhaal22@643
   105
        ERROR( "Init: cannot set channel count (%s)\n", snd_strerror( err ) );
bhaal22@643
   106
        return FALSE;
bhaal22@643
   107
    }
bhaal22@643
   108
bhaal22@643
   109
    // frames = 4410;
bhaal22@643
   110
    // snd_pcm_hw_params_set_period_size_near( _soundDevice, hw_params, &frames,
bhaal22@643
   111
    //                                     &dir );
bhaal22@643
   112
bhaal22@643
   113
    // Apply the hardware parameters that we've set.
bhaal22@643
   114
    err = snd_pcm_hw_params( _soundDevice, hw_params );
bhaal22@643
   115
    if ( err < 0 ) {
bhaal22@643
   116
        DEBUG( "Init: cannot set parameters (%s)\n", snd_strerror( err ) );
bhaal22@643
   117
        return FALSE;
bhaal22@643
   118
    } else {
bhaal22@643
   119
        DEBUG( "Audio device parameters have been set successfully." );
bhaal22@643
   120
    }
bhaal22@643
   121
bhaal22@643
   122
    snd_pcm_hw_params_get_period_size( hw_params, &frames, &dir );
bhaal22@643
   123
    DEBUG( "period size = %d\n", frames );
bhaal22@643
   124
bhaal22@643
   125
    // Get the buffer size.
bhaal22@643
   126
    snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
bhaal22@643
   127
    DEBUG("Buffer Size = %d\n", bufferSize);
bhaal22@643
   128
bhaal22@643
   129
    // If we were going to do more with our sound device we would want to store
bhaal22@643
   130
    // the buffer size so we know how much data we will need to fill it with.
bhaal22@643
   131
bhaal22@643
   132
    //cout << "Init: Buffer size = " << bufferSize << " frames." << endl;
bhaal22@643
   133
bhaal22@643
   134
    // Display the bit size of samples.
bhaal22@643
   135
    //cout << "Init: Significant bits for linear samples = " << snd_pcm_hw_params_get_sbits(hw_params) << endl;
bhaal22@643
   136
bhaal22@643
   137
    // Free the hardware parameters now that we're done with them.
bhaal22@643
   138
    snd_pcm_hw_params_free( hw_params );
bhaal22@643
   139
bhaal22@643
   140
    // Set the start threshold to reduce inter-buffer gaps
bhaal22@643
   141
    snd_pcm_sw_params_alloca( &sw_params );
bhaal22@643
   142
    snd_pcm_sw_params_current( _soundDevice, sw_params );
nkeynes@880
   143
    snd_pcm_sw_params_set_start_threshold( _soundDevice, sw_params, bufferSize );
bhaal22@643
   144
    err = snd_pcm_sw_params( _soundDevice, sw_params );
bhaal22@643
   145
    if( err < 0 ) {
nkeynes@736
   146
        ERROR("Unable to set sw params for alsa driver: %s\n", snd_strerror(err));
nkeynes@736
   147
        return FALSE;
bhaal22@643
   148
    } 
bhaal22@643
   149
bhaal22@643
   150
    err = snd_pcm_prepare( _soundDevice );
bhaal22@643
   151
    if ( err < 0 ) {
bhaal22@643
   152
        ERROR( "Init: cannot prepare audio interface for use (%s)\n",
nkeynes@736
   153
                snd_strerror( err ) );
bhaal22@643
   154
        return FALSE;
bhaal22@643
   155
    }
bhaal22@643
   156
    return TRUE;
bhaal22@643
   157
}
bhaal22@643
   158
nkeynes@1024
   159
static gboolean audio_alsa_process_buffer( audio_buffer_t buffer )
bhaal22@643
   160
{
bhaal22@643
   161
    int err;
bhaal22@643
   162
    int length;
bhaal22@643
   163
bhaal22@643
   164
bhaal22@643
   165
    length = buffer->length / frame_bytes;
bhaal22@643
   166
bhaal22@643
   167
    err = snd_pcm_writei( _soundDevice, buffer->data, length );
bhaal22@643
   168
    if( err == -EPIPE ) {
nkeynes@736
   169
        snd_pcm_prepare( _soundDevice );
bhaal22@643
   170
    } else if( err == -ESTRPIPE ) {
nkeynes@736
   171
        snd_pcm_resume( _soundDevice );
bhaal22@643
   172
    }
bhaal22@643
   173
bhaal22@643
   174
    return TRUE;
bhaal22@643
   175
}
bhaal22@643
   176
bhaal22@643
   177
nkeynes@1024
   178
static gboolean audio_alsa_shutdown(  )
bhaal22@643
   179
{
bhaal22@643
   180
    return TRUE;
bhaal22@643
   181
}
bhaal22@643
   182
bhaal22@643
   183
bhaal22@643
   184
nkeynes@1024
   185
static struct audio_driver audio_alsa_driver = { 
nkeynes@736
   186
        "alsa",
nkeynes@736
   187
        N_("Linux ALSA system driver"),
nkeynes@1024
   188
        40,
nkeynes@736
   189
        DEFAULT_SAMPLE_RATE,
nkeynes@736
   190
        DEFAULT_SAMPLE_FORMAT,
nkeynes@736
   191
        audio_alsa_init,
nkeynes@736
   192
        NULL,
nkeynes@736
   193
        audio_alsa_process_buffer,
nkeynes@736
   194
        NULL,
nkeynes@736
   195
        audio_alsa_shutdown
bhaal22@643
   196
};
nkeynes@1024
   197
nkeynes@1024
   198
static gboolean audio_alsa_static_init( void )
nkeynes@1024
   199
{
nkeynes@1073
   200
    lxdream_register_config_group( "alsa", &alsa_config );
nkeynes@1024
   201
    audio_register_driver( &audio_alsa_driver );
nkeynes@1024
   202
    return TRUE;
nkeynes@1024
   203
}
nkeynes@1024
   204
nkeynes@1024
   205
DEFINE_PLUGIN( PLUGIN_AUDIO_DRIVER, "alsa", audio_alsa_static_init );
.