Audio CD Player
/usr/photon/dll/audiocd.so (Photon)
/lib/dll/audiocd_noph.so
The Audio CD player plugins play Audio CDs. They're multitrack plugins that control the playback of an audio CD drive.
The audiocd_noph.so player is launched by typing playAudioCd at the command line.
Calling MvInit() sets the value of MvPluginCtrl_t.MvPluginFlags_t pflags to MV_HASDFLTURL.
See the Resource Profile Estimates and Library Dependencies appendix.
Valid commands for the Audio CD plugin are:
CMD_PLUGIN_CLOSE
CMD_PLUGIN_GET_STATUS
CMD_PLUGIN_MUTE
CMD_PLUGIN_OPEN_URLS
CMD_PLUGIN_PAUSE
CMD_PLUGIN_SEEK_RELATIVE
CMD_PLUGIN_SEEK_TO
CMD_PLUGIN_SET_GUI_STATUS
CMD_PLUGIN_SET_PARAMETER
CMD_PLUGIN_START
CMD_PLUGIN_STOP
This sample callback handler is used by phplay to analyze state changes and status information. After verifying that the plugin handle is still valid, the value of the MvEventFlags_t change variable is examined to determine which field of the MvPluginStatus_t const *pst structure is valid.
Values that may be used for MvEventFlags_t change include:
MVS_DURATION
MVS_ERRORMSG
MVS_FLAGS
MVS_GUI_STATUS
MVS_MEDIA
MVS_PLUGIN_STATE
MVS_POSITION
MVS_VPSIZE
void cdaudio_vcb( MvPluginCtrl_t *ctrl, MvEventFlags_t change, MvPluginStatus_t const *pst )
{
PtArg_t args[2];
const char *status = "No plugin";
if( mplayer.pctrl == NULL )
{ //this plugin has been closed
if( pst->state == MV_DEAD )
{ // plugin is ready for destruction
UnloadDll( ctrl );
free( ctrl );
// reset plugin count
mplayer.pluginIsLoaded = FALSE;
}
// show the correct pause/play button
SetPlayPauseButton( TRUE );
return;
}
/* CHECK IF PLUGIN STATE HAS CHANGE */
if( change & MVS_PLUGIN_STATE )
{ //plugin state has change
switch( pst->state )
{
case MV_DEAD:
status ="Dead";
mplayer.pluginIsLoaded = FALSE;
SetStopEjectButton( FALSE );
cbBaseClose( 0, 0, 0 );
return;
case MV_CLOSED:
status = ( mplayer.pctrl->lastst == MV_OPENING ) ? "Open failed" : "No Clip";
break;
case MV_OPENING:
status = "Opening";
break;
case MV_STOPPED:
status = ( mplayer.pctrl->lastst == MV_OPENING ) ? "Opened" : "Stopped";
break;
case MV_PAUSED:
status = "Paused";
break;
case MV_PREFETCHING:
status = "Prefetching";
break;
case MV_PLAYING:
status = "Playing";
mplayer.played = 1;
// arm the timer with the right frequency for
// mplayer get_status() call to the plugin
PtSetArg( &args[0], Pt_ARG_TIMER_INITIAL,
mplayer.playback_parms.status_frequency, 0 );
PtSetArg( &args[1], Pt_ARG_TIMER_REPEAT,
mplayer.playback_parms.status_frequency, 0 );
PtSetResources( ABW_timer, 2, args );
break;
default:
status = "Unknown";
break;
}
//update cdrom keypad display
UpdateCdKeypad( pst->state );
// reset the timer for mplayer get_status() call to the plugin
// only if it has been arm and the plugin state has change
if( mplayer.pctrl->lastst == MV_PLAYING )
{
PtSetArg( &args[0], Pt_ARG_TIMER_INITIAL,0, 0 );
PtSetArg( &args[1], Pt_ARG_TIMER_REPEAT,0, 0 );
PtSetResources( ABW_timer, 2, args );
}
// show the correct play /pause button
setbuttons( pst->state);
// update mplayer state flag
mplayer.pctrl->lastst = pst->state;
//update GUI status label with new state
PtSetArg( &args[0], Pt_ARG_TEXT_STRING, status, 0 );
PtSetResources( ABW_cd_statusLabel, 1, args );
}
/* CHECK IF PLUGIN STATUS FLAG HAS CHANGE */
if( change & MVS_FLAGS )
{// flags is valid. the only one supported is MVP_FULLSCREEN = 0x01
mplayer.pctrl->psflags = pst->flags;
}
/* CHECK IF PLUGIN WANT TO ADJUST PHPLAY VOLUME SETTING */
if( change & MVS_MEDIA )
{
if( pst->media_info->which & MV_MEDIA_AUDIO_INFO )
{
PtSetArg( &args[0], Pt_ARG_GAUGE_VALUE, pst->media_info->audio->volume, 0 );
PtSetResources( ABW_PtSlider_volume, 1, args );
PtSetArg( &args[0], Pt_ARG_FLAGS,
(pst->media_info->audio->reserve_1) ? Pt_SET :~Pt_SET, Pt_SET );
PtSetResources( ABW_muteButton, 1, args );
return;
}
}
/* CHECK IF PLUGIN MEDIA INFO IS VALID */
if( change & MVS_MEDIA )
// media_info is valid and points to new media
{
if( mplayer.pctrl->lastst >= MV_STOPPED )
{// last state was MV_STOPPED, MV_PAUSED, MV_PREFETCHING, or MV_PLAYING
const char* title = pst->media_info->title;
if( title )
{
PtSetArg( &args[0], Pt_ARG_TEXT_STRING, title, 0 );
PtSetResources( ABW_cd_infoLabel, 1, args );
}
//PtSetArg( &args[0], Pt_ARG_TEXT_STRING, pst->media_info->moreinfo, 0 );
//PtSetResources( ABW_cd_moreInfoLabel, 1, args );
mplayer.pctrl->mediaType = pst->media_info->type;
mplayer.pctrl->duration = pst->media_info->duration;
if( mplayer.pctrl->mediaType & MV_MEDIA_SEEKABLE && mplayer.pctrl->duration )
{
PtSetArg( &args[0], Pt_ARG_FLAGS, 0, Pt_BLOCKED | Pt_GHOST );
PtSetResources( ABW_curpos, 1, args );
}
if( pst->media_info->type & MV_MEDIA_PLAYLIST )
{ // the plugin new media info is a playlist
int track;
// update base window info label
if( title && title[0])
// check if title is not an empty string
{
PtSetArg( &args[0], Pt_ARG_TEXT_STRING, title, 0 );
PtSetResources( ABW_baseInfo, 1, args );
}
ControllerGetPluginList();
track = ControllerGetActiveTrack();
cdrom.buttonCount = pst->media_info->plcount;
ControllerOpenIndex( NULL, track );
InitCdromGui( );
}
else
{
// the new plugin media info is not a play list
int track;
MvCommandData_t cmdData = {0};
//track = ControllerAddUrl( pst->media_info->url, pst->media_info->title );
//ControllerSetActiveTrack( track );
if( pst->media_info->duration )
{
// adjust the maximum range of the progress bar widget
PtSetArg( &args[0], Pt_ARG_GAUGE_MAXIMUM, pst->media_info->duration, 0 );
PtSetResources( ABW_curpos, 1, args );
}
// repositioning of the widget to show beginning of time frame
PtSetArg( &args[0], Pt_ARG_GAUGE_VALUE, 0, 0 );
PtSetResources( ABW_curpos, 1, args );
if(( mplayer.playback_parms.status_frequency =
mplayer.pctrl->duration / POS_SLIDER_WIDTH ) > 100 )
{
mplayer.playback_parms.status_frequency = 100;
}
cmdData.pluginCtrl = &mplayer.pctrl->mv;
cmdData.cmdType = CMD_PLUGIN_SET_PARAMETER;
cmdData.param = &mplayer.playback_parms;
cmdData.which = MVP_STATUS_FREQ | MVP_AUDIO;
mplayer.pctrl->mv.calls->command( &cmdData );
}
}
else
{// last state was MV_DEAD, MV_CLOSED, or MV_OPENING
// reset GUI cursor position
PtSetArg( &args[0], Pt_ARG_GAUGE_VALUE, 0, 0 );
PtSetResources( ABW_curpos, 1, args );
// make it impossible to move the cursor from the GUI
PtSetArg( &args[0], Pt_ARG_FLAGS, ~0, Pt_BLOCKED | Pt_GHOST );
PtSetResources( ABW_curpos, 1, args );
}
}
/* CHECK IF PLUGIN POSITION IS VALID */
if( change & MVS_POSITION )
{ // position is valid
plassert( mplayer.pctrl->duration != 0, "MVS_POSITION is set although duration is 0" );
if( !( mplayer.cursorIsDrag ) )
{
// update background cursor position
mplayer.pctrl->lastpos = pst->position;
// update cursor position
//fprintf(stderr,"setting position to %d\n",pst->position);
PtSetArg( &args[0], Pt_ARG_GAUGE_VALUE, pst->position, 0 );
PtSetResources( ABW_curpos, 1, args );
if( ( pst->position / 100 ) != mplayer.pctrl->lrpos )
{
CdUpdatePosition( pst->position, mplayer.pctrl->duration );
}
}
}
/* CHECK IF PLUGIN HAS AN ERROR MESSAGE */
if( change & MVS_ERRORMSG )
{ // there's an error message in errmsg
popup_error( pst->errormsg );
cbBaseClose( 0, 0, 0 );
return;
}
/* CHECK IF MPLAYER REQUEST PLUGIN TO UPDATE GUI */
if( change & MVS_GUI_STATUS )
{
UpdateCdGuiState();
}
/* CHECK IF PLUGIN IS WAITING FOR NEXT COMMAND */
if( mplayer.pctrl->lastst == MV_STOPPED && mplayer.played && mplayer.vcbLock == 0 )
{
mplayer.vcbLock = 1;
mplayer.played = 0;
if( mplayer.playIsSet )
{
int track = ControllerGetNextTrack();
MvCommandData_t cmdData = {0};
if( track != -1 )
{
const char *url = ControllerGetUrl( track );
MvCommandData_t cmdData = {0};
if( ControllerPluginChange( url ))
{
//ControllerOpenIndex( NULL, track );
}
else
{
// play the selection
ControllerSetActiveTrack( track );
cmdData.pluginCtrl = &mplayer.pctrl->mv;
cmdData.cmdType = CMD_PLUGIN_OPEN_URLS;
cmdData.which = MVP_DELTA;
cmdData.nodeString = getenv("HOSTNAME");
cmdData.displayString = getenv("PHOTON");
cmdData.urls = (char**) &url;
cmdData.param = &mplayer.playback_parms;
mplayer.playback_parms.delta = 1;
mplayer.pctrl->mv.calls->command( &cmdData );
memset( &cmdData, 0, sizeof(cmdData) );
cmdData.pluginCtrl = &mplayer.pctrl->mv;
cmdData.cmdType = CMD_PLUGIN_START;
cmdData.which = MVP_NONE;
mplayer.pctrl->mv.calls->command( &cmdData );
}
}
else
{
int next = ControllerGetFirstSelectedTrack();
const char *url = ControllerGetUrl( next );
// stop the plugin
mplayer.playIsSet = FALSE;
memset( &cmdData, 0, sizeof(cmdData) );
cmdData.pluginCtrl = &mplayer.pctrl->mv;
cmdData.cmdType = CMD_PLUGIN_STOP;
cmdData.which = MVP_NONE;
mplayer.pctrl->mv.calls->command( &cmdData );
// open the first selected track
memset( &cmdData, 0, sizeof(cmdData) );
ControllerSetActiveTrack( next );
cmdData.pluginCtrl = &mplayer.pctrl->mv;
cmdData.cmdType = CMD_PLUGIN_OPEN_URLS;
cmdData.which = MVP_DELTA;
cmdData.nodeString = getenv("HOSTNAME");
cmdData.displayString = getenv("PHOTON");
cmdData.urls = (char**) &url;
cmdData.param = &mplayer.playback_parms;
mplayer.playback_parms.delta = (url) ? 1 : 0;
mplayer.pctrl->mv.calls->command( &cmdData );
}
}
mplayer.vcbLock = 0;
}
}
See the playAudioCd.c example in the Appendix.