⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 alsa.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
error:    snd_pcm_close( p_sys->p_snd_pcm );#ifdef ALSA_DEBUG    snd_output_close( p_sys->p_snd_stderr );#endif    free( p_sys );    return VLC_EGENERIC;}/***************************************************************************** * Play: nothing to do *****************************************************************************/static void Play( aout_instance_t *p_aout ){    if( !p_aout->output.p_sys->b_playing )    {        p_aout->output.p_sys->b_playing = 1;        /* get the playing date of the first aout buffer */        p_aout->output.p_sys->start_date =            aout_FifoFirstDate( p_aout, &p_aout->output.fifo );        /* wake up the audio output thread */        vlc_mutex_lock( &p_aout->output.p_sys->lock );        vlc_cond_signal( &p_aout->output.p_sys->wait );        vlc_mutex_unlock( &p_aout->output.p_sys->lock );    }}/***************************************************************************** * Close: close the ALSA device *****************************************************************************/static void Close( vlc_object_t *p_this ){    aout_instance_t *p_aout = (aout_instance_t *)p_this;    struct aout_sys_t * p_sys = p_aout->output.p_sys;    int i_snd_rc;    /* make sure the audio output thread is waken up */    vlc_mutex_lock( &p_aout->output.p_sys->lock );    vlc_cond_signal( &p_aout->output.p_sys->wait );    vlc_mutex_unlock( &p_aout->output.p_sys->lock );    p_aout->b_die = VLC_TRUE;    vlc_thread_join( p_aout );    p_aout->b_die = VLC_FALSE;    i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm );    if( i_snd_rc > 0 )    {        msg_Err( p_aout, "failed closing ALSA device (%s)",                         snd_strerror( i_snd_rc ) );    }#ifdef ALSA_DEBUG    snd_output_close( p_sys->p_snd_stderr );#endif    free( p_sys );}/***************************************************************************** * ALSAThread: asynchronous thread used to DMA the data to the device *****************************************************************************/static int ALSAThread( aout_instance_t * p_aout ){    p_aout->output.p_sys->p_status =        (snd_pcm_status_t *)malloc(snd_pcm_status_sizeof());    /* Wait for the exact time to start playing (avoids resampling) */    vlc_mutex_lock( &p_aout->output.p_sys->lock );    if( !p_aout->output.p_sys->start_date )        vlc_cond_wait( &p_aout->output.p_sys->wait,                       &p_aout->output.p_sys->lock );    vlc_mutex_unlock( &p_aout->output.p_sys->lock );    mwait( p_aout->output.p_sys->start_date - AOUT_PTS_TOLERANCE / 4 );    while ( !p_aout->b_die )    {        ALSAFill( p_aout );    }    free( p_aout->output.p_sys->p_status );    return 0;}/***************************************************************************** * ALSAFill: function used to fill the ALSA buffer as much as possible *****************************************************************************/static void ALSAFill( aout_instance_t * p_aout ){    struct aout_sys_t * p_sys = p_aout->output.p_sys;    aout_buffer_t * p_buffer;    snd_pcm_status_t * p_status = p_sys->p_status;    int i_snd_rc;    mtime_t next_date;    /* Fill in the buffer until space or audio output buffer shortage */    {        /* Get the status */        i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );        if( i_snd_rc < 0 )        {            msg_Err( p_aout, "unable to get the device's status (%s)",                             snd_strerror( i_snd_rc ) );            msleep( p_sys->i_period_time >> 1 );            return;        }        /* Handle buffer underruns and reget the status */        if( snd_pcm_status_get_state( p_status ) == SND_PCM_STATE_XRUN )        {            /* Prepare the device */            i_snd_rc = snd_pcm_prepare( p_sys->p_snd_pcm );            if( i_snd_rc == 0 )            {                msg_Dbg( p_aout, "recovered from buffer underrun" );                /* Reget the status */                i_snd_rc = snd_pcm_status( p_sys->p_snd_pcm, p_status );                if( i_snd_rc < 0 )                {                    msg_Err( p_aout, "unable to get the device's status after "                             "recovery (%s)", snd_strerror( i_snd_rc ) );                    msleep( p_sys->i_period_time >> 1 );                    return;                }            }            else            {                msg_Err( p_aout, "unable to recover from buffer underrun" );                msleep( p_sys->i_period_time >> 1 );                return;            }            /* Underrun, try to recover as quickly as possible */            next_date = mdate();        }        else        {            /* Here the device should be either in the RUNNING state.             * p_status is valid. */#if 0    /* This apparently does not work correctly in Alsa 1.0.11 */            snd_pcm_status_get_tstamp( p_status, &ts_next );            next_date = (mtime_t)ts_next.tv_sec * 1000000 + ts_next.tv_usec;            if( next_date )            {                next_date += (mtime_t)snd_pcm_status_get_delay(p_status)                        * 1000000 / p_aout->output.output.i_rate;            }            else#endif            {                /* With screwed ALSA drivers the timestamp is always zero;                 * use another method then */                snd_pcm_sframes_t delay = 0;                snd_pcm_delay( p_sys->p_snd_pcm, &delay );                next_date = mdate() + (mtime_t)(delay) * 1000000 /                          p_aout->output.output.i_rate                        * p_aout->output.output.i_frame_length;            }        }        p_buffer = aout_OutputNextBuffer( p_aout, next_date,                        (p_aout->output.output.i_format ==                         VLC_FOURCC('s','p','d','i')) );        /* Audio output buffer shortage -> stop the fill process and wait */        if( p_buffer == NULL )        {            msleep( p_sys->i_period_time >> 1 );            return;        }        i_snd_rc = snd_pcm_writei( p_sys->p_snd_pcm, p_buffer->p_buffer,                                   p_buffer->i_nb_samples );        if( i_snd_rc < 0 )        {            msg_Err( p_aout, "write failed (%s)",                             snd_strerror( i_snd_rc ) );        }        aout_BufferFree( p_buffer );    }}static void GetDevicesForCard(module_config_t *p_item, int i_card);static void GetDevices( module_config_t *p_item );/***************************************************************************** * config variable callback *****************************************************************************/static int FindDevicesCallback( vlc_object_t *p_this, char const *psz_name,                               vlc_value_t newval, vlc_value_t oldval, void *p_unused ){    module_config_t *p_item;    int i;    p_item = config_FindConfig( p_this, psz_name );    if( !p_item ) return VLC_SUCCESS;    /* Clear-up the current list */    if( p_item->i_list )    {        /* Keep the first entrie */        for( i = 1; i < p_item->i_list; i++ )        {            free( p_item->ppsz_list[i] );            free( p_item->ppsz_list_text[i] );        }        /* TODO: Remove when no more needed */        p_item->ppsz_list[i] = NULL;        p_item->ppsz_list_text[i] = NULL;    }    p_item->i_list = 1;    GetDevices( p_item );    /* Signal change to the interface */    p_item->b_dirty = VLC_TRUE;    return VLC_SUCCESS;}static void GetDevicesForCard(module_config_t *p_item, int i_card){    int i_pcm_device = -1;    int i_err = 0;    snd_pcm_info_t *p_pcm_info;    snd_ctl_t *p_ctl;    char psz_dev[64];    char *psz_card_name;        sprintf(psz_dev, "hw:%i", i_card);        if (( i_err = snd_ctl_open(&p_ctl, psz_dev, 0)) < 0 )    {        return;    }        if ((i_err = snd_card_get_name(i_card, &psz_card_name)) != 0)    {        psz_card_name = _("Unknown soundcard");    }    snd_pcm_info_alloca(&p_pcm_info);    for (;;)    {        char *psz_device, *psz_descr;        if ((i_err = snd_ctl_pcm_next_device(p_ctl, &i_pcm_device)) < 0)        {            i_pcm_device = -1;        }        if ( i_pcm_device < 0 )            break;        snd_pcm_info_set_device(p_pcm_info, i_pcm_device);        snd_pcm_info_set_subdevice(p_pcm_info, 0);        snd_pcm_info_set_stream(p_pcm_info, SND_PCM_STREAM_PLAYBACK);        if ((i_err = snd_ctl_pcm_info(p_ctl, p_pcm_info)) < 0)        {            if (i_err != -ENOENT)            {/*                printf("get_devices_for_card(): "                         "snd_ctl_pcm_info() "                         "failed (%d:%d): %s.\n", i_card,                         i_pcm_device, snd_strerror(-i_err));*/            }            continue;        }        asprintf( &psz_device, "hw:%d,%d", i_card, i_pcm_device );        asprintf( &psz_descr, "%s: %s (%s)", psz_card_name,                  snd_pcm_info_get_name(p_pcm_info), psz_device );        p_item->ppsz_list =            (char **)realloc( p_item->ppsz_list,                              (p_item->i_list + 2) * sizeof(char *) );        p_item->ppsz_list_text =            (char **)realloc( p_item->ppsz_list_text,                              (p_item->i_list + 2) * sizeof(char *) );        p_item->ppsz_list[ p_item->i_list ] = psz_device;        p_item->ppsz_list_text[ p_item->i_list ] = psz_descr;        p_item->i_list++;        p_item->ppsz_list[ p_item->i_list ] = NULL;        p_item->ppsz_list_text[ p_item->i_list ] = NULL;                    }    snd_ctl_close( p_ctl );}static void GetDevices( module_config_t *p_item ){    int i_card = -1;    int i_err = 0;        if ((i_err = snd_card_next(&i_card)) != 0)    {//        g_warning("snd_next_card() failed: %s", snd_strerror(-err));        return;    }        while (i_card > -1)    {        GetDevicesForCard(p_item, i_card);        if ((i_err = snd_card_next(&i_card)) != 0)        {//            g_warning("snd_next_card() failed: %s",//                  snd_strerror(-err));            break;        }    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -