diff -ur phmad-orig/src/madthread.c phmad/src/madthread.c --- phmad-orig/src/madthread.c Mon Sep 10 01:40:02 2001 +++ phmad/src/madthread.c Sat Oct 27 02:54:18 2001 @@ -36,7 +36,7 @@ event.flags = Ph_EVENT_DIRECT; event.processing_flags = Ph_FAKE_EVENT; - PhEmit( &event, 0, 0 ); + /*PhEmit( &event, 0, 0 );*/ } return 0; @@ -92,6 +92,7 @@ madthread_data_t *mdata = data; int moved; int bytes; + int cnt; int ret; moved = 0; @@ -108,9 +109,38 @@ memmove( mdata->inbuffer, stream->next_frame, moved ); } - bytes = read( mdata->fd, mdata->inbuffer + moved, - sizeof( mdata->inbuffer ) - moved ); + /* Copy bytes from the read thread buffer */ + bytes = sizeof( mdata->inbuffer ) - moved; + /* Number of bytes currently in the buffer */ + pthread_mutex_lock( &mdata->buffer_mutex ); + cnt = mdata->iptr - mdata->optr; + if(cnt < 0) cnt += sizeof( mdata->buffer ); + + if( bytes > cnt ) + bytes = cnt; + + /* Number of bytes from offset to end of buffer */ + cnt=sizeof( mdata->buffer ) - mdata->optr; + if( bytes > cnt ) { + /* Have to copy two separate sections: tail, then head */ + memcpy(mdata->inbuffer + moved, mdata->buffer + mdata->optr, cnt); + /* Number of bytes to copy from the head */ + mdata->optr = bytes - cnt; + memcpy(mdata->inbuffer + moved + cnt, mdata->buffer, mdata->optr); + } else { + /* Can copy one section */ + memcpy(mdata->inbuffer + moved, mdata->buffer + mdata->optr, bytes); + mdata->optr += bytes; + if(mdata->optr >= sizeof( mdata->buffer )) + mdata->optr -= sizeof( mdata->buffer ); + } + /* Give a signal to wake the reading thread so it reads more data */ + pthread_cond_signal( &mdata->buffer_cond ); + pthread_mutex_unlock( &mdata->buffer_mutex ); + +//fprintf(stderr,"mad_flow input copied %d bytes\n",bytes); + if( bytes <= 0 ) return MAD_FLOW_STOP; @@ -279,7 +309,48 @@ return MAD_FLOW_IGNORE; } +void *bufferthread( void *p ) +{ + madthread_data_t *mdata; + int rd; + int avail; +//fprintf(stderr,"bufferthread running\n"); + + mdata = (madthread_data_t *)p; + + pthread_mutex_lock(&mdata->buffer_mutex); + while(!mdata->end_buffer_thread) { + avail=mdata->optr - mdata->iptr; + if(avail<=0) avail += sizeof(mdata->buffer); +//fprintf(stderr,"optr=%d, iptr=%d, avail=%d\n",mdata->optr,mdata->iptr,avail); + /* If no room left in the buffer, wait until some is removed */ + if(avail == 1) { + pthread_cond_wait(&mdata->buffer_cond,&mdata->buffer_mutex); + } else { + pthread_mutex_unlock( &mdata->buffer_mutex ); + /* Always keep at least one byte empty so there is no empty-full confusion */ + avail--; + rd = sizeof(mdata->buffer) - mdata->iptr; + if(rd > avail) rd=avail; + rd=read(mdata->fd_mp3, mdata->buffer + mdata->iptr, rd); +//fprintf(stderr,"Read %d bytes from file\n",rd); + if(rd<=0) + break; + /* Update the buffer pointers */ + pthread_mutex_lock( &mdata->buffer_mutex ); + mdata->iptr += rd; + if(mdata->iptr >= sizeof( mdata->buffer )) + mdata->iptr -= sizeof( mdata->buffer ); + } + } + pthread_mutex_unlock( &mdata->buffer_mutex ); +//fprintf(stderr,"bufferthread returning\n"); + + pthread_cond_signal( &mdata->buffer_cond ); + return 0; +} + void *madthread( void *p ) { madthread_data_t *mdata; @@ -322,6 +393,8 @@ madthread_data_t *data; struct sched_param param; struct stat sbuf; + int mp3play_pipe[2]; /* For pipe-from-cat mod */ + int status; /* Status returned by the child process */ policy = 0; ret = 0; @@ -335,15 +408,41 @@ data->audio_stats = audio_stats; data->event_widget = event_widget; - data->fd = open( filename, O_RDONLY ); - if( data->fd == -1 ) + stat( filename, &sbuf ); + data->audio_stats->filelen = sbuf.st_size; + + data->fd_mp3 = open( filename, O_RDONLY ); + if( data->fd_mp3 == -1 ) { +fprintf(stderr,"Failed to open mp3 file %s\n",filename); free( data ); return -1; } + data->end_buffer_thread = 0; + data->optr = 0; + /* Start with half of the buffer filled to get us going */ + data->iptr = read(data->fd_mp3, data->buffer, sizeof( data->buffer )/2 ); + if( data->iptr <= 0) { + fprintf(stderr,"The mp3 file appears to be empty"); + close(data->fd_mp3); + free( data ); + return -1; + } - stat( filename, &sbuf ); - data->audio_stats->filelen = sbuf.st_size; + /* Make a file buffering thread */ + pthread_cond_init( &data->buffer_cond, NULL ); + pthread_mutex_init( &data->buffer_mutex, NULL ); + pthread_attr_init( &pattr ); + pthread_create( &data->buffer_tid, &pattr, bufferthread, data ); + if( ret != EOK ) + { + perror("Create buffer thread"); + close(data->fd_mp3); + pthread_cond_destroy( &data->buffer_cond); + pthread_mutex_destroy( &data->buffer_mutex); + free( data ); + return -1; + } ret = pthread_mutex_init( &data->mutex, NULL ); ret |= pthread_cond_init( &data->cond, NULL ); @@ -360,17 +459,33 @@ ret = pthread_create( &data->thread, &pattr, madthread, data ); if( ret == EOK ) { +//fprintf(stderr,"Thread create succeeded, waiting for mutex\n"); *mdata = data; pthread_cond_wait( &data->cond, &data->mutex ); pthread_mutex_unlock( &data->mutex ); +//fprintf(stderr,"Start returning\n"); return 0; } +//fprintf(stderr,"Thread create failed\n"); pthread_mutex_unlock( &data->mutex ); } - close( data->fd ); +//fprintf(stderr,"Set priority levels failed\n"); + + /* Kick the I/O thread to make sure it exits */ + pthread_mutex_lock( &data->buffer_mutex ); + data->end_buffer_thread = 1; + data->iptr = data->optr = 0; + close( data->fd_mp3 ); + pthread_cond_signal( &data->buffer_cond ); + pthread_mutex_unlock( &data->buffer_mutex ); + pthread_mutex_destroy( &data->mutex ); pthread_cond_destroy( &data->cond ); + + pthread_mutex_destroy( &data->buffer_mutex ); + pthread_cond_destroy( &data->buffer_cond ); + free( data ); *mdata = NULL; return -1; @@ -400,9 +515,12 @@ { madthread_data_t *data; int ret; + int status; /* Status returned by child process */ data = *mdata; +//fprintf(stderr,"Stopping the mad thread\n"); + /* Unlock the mutex */ if( !data->paused ) pthread_mutex_lock( &data->mutex ); @@ -413,17 +531,29 @@ pthread_mutex_unlock( &data->mutex ); +//fprintf(stderr,"Waiting for thread to cleanup\n"); /* Wait for thread to cleanup */ pthread_join( data->thread, NULL ); +//fprintf(stderr,"Draing the current output to unblock the stopped thread\n"); /* Drain the current output to unblock the stopped thread */ snd_pcm_playback_drain( data->audio->pcm ); /* Cleanup allocated resources */ - close( data->fd ); + /* Kick the I/O thread to make sure it exits */ + pthread_mutex_lock( &data->buffer_mutex ); + data->end_buffer_thread = 1; + data->iptr = data->optr = 0; + close( data->fd_mp3 ); + pthread_cond_signal( &data->buffer_cond ); + pthread_mutex_unlock( &data->buffer_mutex ); + pthread_mutex_destroy( &data->mutex ); pthread_cond_destroy( &data->cond ); + pthread_mutex_destroy( &data->buffer_mutex ); + pthread_cond_destroy( &data->buffer_cond ); + if( data->audio->mixer != NULL ) phmad_close_mixer( data->audio ); @@ -433,7 +563,7 @@ free( data ); *mdata = NULL; - +//fprintf(stderr,"madthread_stop returning\n"); return 0; } diff -ur phmad-orig/src/phmad.c phmad/src/phmad.c --- phmad-orig/src/phmad.c Mon Sep 10 01:40:10 2001 +++ phmad/src/phmad.c Sat Oct 20 16:29:57 2001 @@ -48,7 +48,7 @@ event.flags = Ph_EVENT_DIRECT; event.processing_flags = Ph_FAKE_EVENT; - PhEmit( &event, 0, 0 ); + /*PhEmit( &event, 0, 0 );*/ } return 0; diff -ur phmad-orig/src/phmad.h phmad/src/phmad.h --- phmad-orig/src/phmad.h Sat Sep 15 15:32:05 2001 +++ phmad/src/phmad.h Sat Oct 27 02:26:10 2001 @@ -73,7 +73,14 @@ pthread_mutex_t mutex; pthread_cond_t cond; pthread_t thread; - int fd; + pthread_t buffer_tid; + pthread_mutex_t buffer_mutex; + pthread_cond_t buffer_cond; + int end_buffer_thread; + int iptr; + int optr; + char buffer[262145]; + int fd_mp3; int file_size; int data_read; phmad_audio_t *audio; diff -ur phmad-orig/src/gcc_ntox86/Makefile phmad/src/gcc_ntox86/Makefile --- phmad-orig/src/gcc_ntox86/Makefile Thu Aug 30 13:55:34 2001 +++ phmad/src/gcc_ntox86/Makefile Sat Oct 20 16:28:32 2001 @@ -38,8 +38,8 @@ CFLAGS = -V$(PLATFORM) -w5 $(OPTIM) $(DEBUG) $(PHABOPTS) -I. CXXFLAGS = $(CFLAGS) -LDFLAGS = -V$(PLATFORM) -Bstatic $(DEBUG) -l phexlib $(ABLIB) $(PHABOPTS) -lmad -lasound -SDFLAGS = -V$(PLATFORM) $(DEBUG) -l phexlib $(ABLIB) $(PHABOPTS) -lasound -Bstatic -lmad +LDFLAGS = -V$(PLATFORM) -Bstatic $(DEBUG) -W l,-rpath,/lib -L/usr/lib -L/lib -l phexlib $(ABLIB) $(PHABOPTS) -lmad -lasound +SDFLAGS = -V$(PLATFORM) $(DEBUG) -W l,-rpath,/lib -L/usr/lib -L/lib -l phexlib $(ABLIB) $(PHABOPTS) -lasound -Bstatic -lmad VPATH = ..