00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <unistd.h>
00021 #include <sys/types.h>
00022 #include <sys/wait.h>
00023 #include <signal.h>
00024 #include <pthread.h>
00025 #include <iostream>
00026 using namespace std;
00027
00028 #include "RioInterfaceTypes.h"
00029 #include "RioInterface.h"
00030 #include "RioMMObject.h"
00031 #include "RioMMMp3.h"
00032 #include "RioError.h"
00033
00034 #include "qevent.h"
00035 #include "qapplication.h"
00036
00037 CRioMMMp3::CRioMMMp3( char *mp3name, unsigned int blocksize, RioBlock numBuffers,
00038 struct timeval RTT_average, RioMMInterface *rio )
00039 :CRioMMObject( mp3name, blocksize, numBuffers , RTT_average )
00040 {
00041 pid = 0;
00042 PlayBuffer = 0;
00043 PlayThreadID = 0;
00044 riomminterface = rio;
00045 NextRequestBlock = numBuffers;
00046 Paused = false;
00047 pthread_mutex_init( &PlayPause, NULL );
00048 }
00049
00050
00051 CRioMMMp3::~CRioMMMp3()
00052 {
00053 if( PlayThreadID != 0 )
00054 pthread_cancel( PlayThreadID );
00055 }
00056
00057
00058 int CRioMMMp3::init()
00059 {
00060 return 0;
00061 }
00062
00063
00064 void CRioMMMp3::PlayBlock( int buf, int size )
00065 {
00066 int sent;
00067 int n, nwrite;
00068
00069 char *buffer = (char *)Request[buf].Buffer;
00070
00071 sent = 0;
00072 while( sent < size )
00073 {
00074 n = size - sent;
00075 if( n > MaxPipeDataSize )
00076 n = MaxPipeDataSize;
00077
00078 pthread_mutex_lock( &PlayPause );
00079 nwrite = write( pipe_mpg123[1], (void*)buffer, n );
00080 pthread_mutex_unlock( &PlayPause );
00081
00082 if( nwrite < 0 )
00083 {
00084 Rioperror("write: pipe mpg123");
00085 }
00086
00087 sent += nwrite;
00088 buffer += nwrite;
00089 }
00090
00091 if( riomminterface )
00092 {
00093 QCustomEvent *event = new QCustomEvent( QEvent::User , &Request[buf].Block );
00094 QApplication::postEvent( (QObject*)riomminterface, event );
00095 }
00096 }
00097
00098
00099 void CRioMMMp3::FastForward()
00100 {
00101 NextRequestBlock += 10;
00102 }
00103
00104
00105 void CRioMMMp3::FastRewind()
00106 {
00107 NextRequestBlock -= 10;
00108 }
00109
00110
00111 void CRioMMMp3::GoTo( RioBlock block )
00112 {
00113 NextRequestBlock = (int) block;
00114 }
00115
00116
00117 void CRioMMMp3::Stop()
00118 {
00119 if( PlayThreadID != 0 )
00120 {
00121 pthread_cancel( PlayThreadID );
00122 if( Paused )
00123 pthread_mutex_unlock( &PlayPause );
00124 }
00125 PlayBuffer = 0;
00126 PlayThreadID = 0;
00127 NextRequestBlock = nBuffers;
00128
00129 CRioMMObject::Stop();
00130 }
00131
00132
00133 void CRioMMMp3::Pause()
00134 {
00135 if( PlayThreadID != 0 )
00136 {
00137 if( Paused )
00138 {
00139 pthread_mutex_unlock( &PlayPause );
00140 Paused = false;
00141 }
00142 else
00143 {
00144 pthread_mutex_lock( &PlayPause );
00145 Paused = true;
00146 }
00147 }
00148 }
00149
00150
00151 void CRioMMMp3::Play()
00152 {
00153 if( PlayThreadID == 0 )
00154 {
00155 if( pthread_create( &PlayThreadID, NULL, &PlayThread, this ) )
00156 {
00157 RioErr << "Could not create play thread" << endl;
00158 return;
00159 }
00160 }
00161 else
00162 {
00163 if( Paused )
00164 {
00165 pthread_mutex_unlock( &PlayPause );
00166 Paused = false;
00167 }
00168 }
00169 }
00170
00171
00172 void CRioMMMp3::WaitEndOfVideo()
00173 {
00174 pthread_join( PlayThreadID, NULL );
00175 PlayThreadID = 0;
00176 }
00177
00178
00179 RioBlock CRioMMMp3::GetCurrentPosition()
00180 {
00181 return( CurrentBlock );
00182 }
00183
00184
00185 RioBlock CRioMMMp3::GetTotalPositions()
00186 {
00187 return( TotalBlocks );
00188 }
00189
00190
00191
00192 void *CRioMMMp3::PlayThread( void *param )
00193 {
00194 int curBlockSize;
00195 bool EOM;
00196 CRioMMMp3 *Mp3;
00197 unsigned int curpos;
00198 unsigned int n_requests;
00199
00200 pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
00201 pthread_cleanup_push( CRioMMMp3::PlayThreadCleanup, param );
00202
00203 Mp3 = (CRioMMMp3 *)param;
00204
00205 Mp3->StartMpg123();
00206 Mp3->Prefetch();
00207 Mp3->WaitPrefetch();
00208
00209 EOM = false;
00210 while( !EOM )
00211 {
00212
00213 curpos = Mp3->PlayBuffer;
00214 n_requests = 0;
00215
00216
00217 if( Mp3->GetBufferStatus( curpos ) == BUFFEREMPTY )
00218 {
00219 usleep( 700000 );
00220 }
00221 else
00222 {
00223 if( Mp3->Request[curpos].Block < Mp3->TotalBlocks-1 )
00224 curBlockSize = Mp3->BlockSize;
00225 else
00226 {
00227 if( Mp3->Request[curpos].Block == Mp3->TotalBlocks-1 )
00228 curBlockSize = Mp3->ObjSize % Mp3->BlockSize;
00229 else
00230 {
00231 RioErr << "Unbounded streams are not supported yet!" << endl;
00232 exit( -1 );
00233 }
00234 }
00235
00236 Mp3->PlayBlock( curpos, curBlockSize );
00237 Mp3->SetBufferStatus( Mp3->PlayBuffer, BUFFEREMPTY );
00238
00239 Mp3->SyncMedia( (void *)Mp3->Request[curpos].Block );
00240 }
00241
00242 Mp3->ReadNextBlock( Mp3->PlayBuffer );
00243
00244 Mp3->PlayBuffer = (curpos + 1 ) % Mp3->nBuffers;
00245 Mp3->CurrentBlock = Mp3->Request[curpos].Block;
00246 if( Mp3->CurrentBlock == Mp3->TotalBlocks - 1 )
00247 EOM = true;
00248 }
00249 sleep( 2 );
00250 pthread_cleanup_pop( 0 );
00251 pthread_exit( NULL );
00252 }
00253
00254
00255 void CRioMMMp3::PlayThreadCleanup( void *param )
00256 {
00257 CRioMMMp3 *Mp3;
00258
00259 Mp3 = (CRioMMMp3 *)param;
00260 kill( Mp3->pid, SIGKILL );
00261 pthread_mutex_unlock( &Mp3->PlayPause );
00262 pthread_mutex_unlock( &Mp3->PlayThreadMutex );
00263 waitpid( Mp3->pid, NULL, 0 );
00264 Mp3->PlayThreadID = 0;
00265 Mp3->Stop();
00266 }
00267
00268 bool CRioMMMp3::ReadNextBlock( unsigned int index )
00269 {
00270 bool status;
00271
00272 status = true;
00273 if( NextRequestBlock < TotalBlocks )
00274 Read( index, NextRequestBlock++ );
00275 else
00276 status = false;
00277
00278 return( status );
00279 }
00280
00281
00282 void CRioMMMp3::StartMpg123()
00283 {
00284
00285 if( pipe( pipe_mpg123 ) < 0 )
00286 {
00287 Rioperror("pipe(). Failed to create pipe to mpg123.");
00288 return;
00289 }
00290
00291
00292 if( dup2( pipe_mpg123[0], 0 ) == -1 )
00293 {
00294 Rioperror("dup2(). Failed to associate pipe to stdin.");
00295 return;
00296 }
00297
00298
00299 if( (pid = fork()) != 0 )
00300 {
00301 if( pid < 0 )
00302 {
00303 Rioperror("fork(). Failed to fork process.");
00304 return;
00305 }
00306 }
00307 else
00308 {
00309
00310 if( execlp( "mpg123","mpg123", "-", NULL ) == -1 )
00311 {
00312 Rioperror( "execlp(): Failed to execute mpg123." );
00313 exit( 1 );
00314 }
00315 }
00316 }