Changeset 5174:c24a2089056a in roaraudio
- Timestamp:
- 10/22/11 12:11:33 (12 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- plugins/alsavs
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
plugins/alsavs/pcm_roar.c
r5168 r5174 46 46 struct roar_alsa_pcm * self = io->private_data; 47 47 int fh; 48 int val; 49 int err; 48 50 49 51 ROAR_DBG("roar_pcm_start(*) = ?"); … … 53 55 return 0; 54 56 55 if ( roar_vio_simple_new_stream_obj(&(self->stream_vio), &(self->roar.con), &(self->stream), 56 self->info.rate, self->info.channels, self->info.bits, self->info.codec, 57 io->stream == SND_PCM_STREAM_PLAYBACK ? ROAR_DIR_PLAY : ROAR_DIR_MONITOR 58 ) == -1 ) { 59 return -EINVAL; 57 if ( (self->vss = roar_vs_new_from_con(&(self->roar.con), &err)) == NULL ) { 58 roar_err_set(err); 59 roar_err_update(); 60 return -errno; 61 } 62 63 if ( roar_vs_stream(self->vss, &(self->info), 64 io->stream == SND_PCM_STREAM_PLAYBACK ? ROAR_DIR_PLAY : ROAR_DIR_MONITOR, 65 &err) == -1 ) { 66 roar_vs_close(self->vss, ROAR_VS_TRUE, NULL); 67 self->vss = NULL; 68 roar_err_set(err); 69 roar_err_update(); 70 return -errno; 71 } 72 73 if ( roar_vs_buffer(self->vss, self->bufsize, &err) == -1 ) { 74 roar_vs_close(self->vss, ROAR_VS_TRUE, NULL); 75 self->vss = NULL; 76 roar_err_set(err); 77 roar_err_update(); 78 return -errno; 79 } 80 81 val = ROAR_VS_ASYNCLEVEL_AUTO; 82 if ( roar_vs_ctl(self->vss, ROAR_VS_CMD_SET_ASYNC, &val, &err) == -1 ) { 83 roar_vs_close(self->vss, ROAR_VS_TRUE, NULL); 84 self->vss = NULL; 85 roar_err_set(err); 86 roar_err_update(); 87 return -errno; 60 88 } 61 89 62 90 if ( self->stream_role != ROAR_ROLE_UNKNOWN ) { 63 if ( roar_stream_set_role(&(self->roar.con), &(self->stream), self->stream_role) == -1 ) { 64 ROAR_WARN("roar_pcm_start(*): Can not set stream role: %i: %s", self->stream_role, roar_error2str(roar_error)); 91 if ( roar_vs_role(self->vss, self->stream_role, &err) == -1 ) { 92 ROAR_WARN("roar_pcm_start(*): Can not set stream role: %s(%i): %s", 93 roar_role2str(self->stream_role), self->stream_role, roar_error2str(roar_error)); 65 94 } 66 95 } 67 96 68 if ( roar_vio_ctl( &(self->stream_vio),97 if ( roar_vio_ctl(roar_vs_vio_obj(self->vss, NULL), 69 98 io->stream == SND_PCM_STREAM_PLAYBACK ? ROAR_VIO_CTL_GET_SELECT_WRITE_FH : 70 99 ROAR_VIO_CTL_GET_SELECT_READ_FH, &fh) != 1 ) { … … 81 110 self->stream_opened = 1; 82 111 83 self->bufptr = 0; 112 //RM: self->bufptr = 0; 113 ROAR_DBG("roar_pcm_start(*): Starting background thread"); 84 114 self->thread_active = 1; // We have to activate the thread before starting it, because the thread lives on that thread_active is 1. 85 115 if ( pthread_create(&(self->thread), NULL, roar_plugin_thread, self) < 0 ) { 86 116 self->thread_active = 0; 117 ROAR_DBG("roar_pcm_start(*) = -1"); 87 118 return -1; 88 119 } 89 120 pthread_mutex_lock(&(self->lock)); // wait for the background thread to wake up. 121 ROAR_DBG("roar_pcm_start(*): background thread was successfully started"); 122 123 ROAR_DBG("roar_pcm_start(*) = 0"); 90 124 return 0; 91 125 } … … 95 129 return; 96 130 97 roar_vio_close(&(self->stream_vio)); 131 roar_vs_close(self->vss, ROAR_VS_TRUE, NULL); 132 self->vss = NULL; 98 133 self->stream_opened = 0; 99 134 self->thread_active = 0; 100 self->bufptr = 0;101 self->last_ptr = 0;102 self->total_written = 0;103 self->has_written = 0;135 //RM: self->bufptr = 0; 136 //RM: self->last_ptr = 0; 137 //RM: self->total_written = 0; 138 //RM: self->has_written = 0; 104 139 } 105 140 … … 198 233 struct roar_alsa_pcm * self = io->private_data; 199 234 int ptr; 235 ssize_t avail; 200 236 201 237 ROAR_DBG("roar_pcm_pointer(*) = ?"); 238 202 239 // Did ALSA just call snd_pcm_reset() or something like that without calling the plugin? 203 240 // We should restart our stream as well. … … 207 244 } 208 245 246 #if 0 209 247 // ALSA has a weird way of calculating how much data can be written to the audio buffer. 210 248 // It uses the formula: … … 218 256 ptr = snd_pcm_bytes_to_frames(io->pcm, self->bufptr); 219 257 pthread_mutex_unlock(&(self->lock)); 258 #else 259 pthread_mutex_lock(&(self->lock)); 260 avail = roar_vs_get_avail_write(self->vss, NULL); 261 pthread_mutex_unlock(&(self->lock)); 262 263 ROAR_DBG("roar_pcm_pointer(*): avail=%lli", (long long int)avail); 264 265 ptr = snd_pcm_bytes_to_frames(io->pcm, self->bufsize - avail); 266 #endif 220 267 221 268 ptr = io->appl_ptr - ptr; … … 261 308 static int roar_pcm_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp) { 262 309 struct roar_alsa_pcm * self = io->private_data; 310 roar_mus_t lat; 263 311 264 312 ROAR_DBG("roar_pcm_delay(*) = ?"); … … 266 314 // TODO: We need to set *delayp the latency in frames. 267 315 pthread_mutex_lock(&(self->lock)); 268 roar_plugin_drain(self); 269 *delayp = snd_pcm_bytes_to_frames(io->pcm, self->bytes_in_buffer); 316 roar_plugin_drain(self); // why do we call this? 317 318 lat = roar_vs_latency2(self->vss, ROAR_VS_BACKEND_DEFAULT, ROAR_VS_NOWAIT, NULL); 319 *delayp = lat * self->info.rate; 320 270 321 pthread_mutex_unlock(&(self->lock)); 271 322 … … 373 424 //self->bufsize = snd_pcm_frames_to_bytes(io->pcm, buffersize); 374 425 self->bufsize = self->info.bits * self->info.channels * buffersize / 8; 375 self->buffer = malloc(self->bufsize);376 if (self->buffer == NULL)377 return -1;378 self->bufptr = 0;426 //RM: self->buffer = malloc(self->bufsize); 427 //RM: if (self->buffer == NULL) 428 //RM: return -1; 429 //RM: self->bufptr = 0; 379 430 380 431 ROAR_DBG("roar_pcm_hw_params(*) Setting buffersize (bytes): %i", (int)self->bufsize); … … 398 449 pthread_cond_destroy(&(self->cond)); 399 450 400 free(self->buffer);451 //RM: free(self->buffer); 401 452 free(self); 402 453 -
plugins/alsavs/roar.h
r5168 r5174 57 57 struct roar_alsa roar; 58 58 struct roar_audio_info info; 59 struct roar_stream stream; 60 struct roar_vio_calls stream_vio; 59 roar_vs_t * vss; 61 60 int stream_role; 62 61 int stream_opened; 63 size_t writec;62 size_t _writec; 64 63 size_t last_ptr; 65 char* buffer;64 char* _buffer; 66 65 size_t bufsize; 67 volatile size_t bufptr;66 volatile size_t _bufptr; 68 67 pthread_t thread; 69 68 pthread_mutex_t lock; … … 71 70 pthread_cond_t cond; 72 71 volatile int thread_active; 73 int bytes_in_buffer;74 volatile int64_t total_written;75 int has_written;76 struct timespec start_tv;72 int _bytes_in_buffer; 73 volatile int64_t _total_written; 74 int _has_written; 75 struct timespec _start_tv; 77 76 }; 78 77 -
plugins/alsavs/thread.c
r5157 r5174 42 42 43 43 44 45 /* 46 * The following function should be re-written: 47 * write in a loop untill all date is written, 48 * if vs write returns less than requested call the thread and ask it to iterate. 49 */ 50 44 51 // Writes to the FIFO buffer. Waits until there is room to write. 45 52 size_t roar_plugin_write(struct roar_alsa_pcm *self, const char *buf, size_t size) { 53 ssize_t ret; 54 55 ROAR_DBG("roar_plugin_write(self=%p, buf=%p, size=%llu) = ?", self, buf, (long long unsigned int)size); 56 57 #if 0 46 58 /* Wait until we have a ready buffer */ 47 59 while (1) { … … 52 64 //fprintf(stderr, "%d + %d : %d\n", (int)self->bufptr, (int)size, (int)self->bufsize); 53 65 pthread_mutex_lock(&(self->lock)); 54 if ( self->bufptr + size <= self->bufsize) {66 if (roar_vs_get_avail_write(self->vss, NULL) >= (ssize_t)size) { 55 67 pthread_mutex_unlock(&(self->lock)); 56 68 break; … … 58 70 pthread_mutex_unlock(&(self->lock)); 59 71 72 ROAR_DBG("roar_plugin_write(self=%p, buf=%p, size=%llu): Send signal", self, buf, (long long unsigned int)size); 60 73 pthread_cond_signal(&(self->cond)); 61 74 /* Sleeps until we can write to the FIFO. */ 75 ROAR_DBG("roar_plugin_write(self=%p, buf=%p, size=%llu): Waiting for answer", self, buf, (long long unsigned int)size); 62 76 pthread_mutex_lock(&(self->cond_lock)); 63 77 pthread_cond_wait(&(self->cond), &(self->cond_lock)); 64 78 pthread_mutex_unlock(&(self->cond_lock)); 65 79 } 66 67 pthread_mutex_lock(&(self->lock)); 68 memcpy(self->buffer + self->bufptr, buf, size); 69 self->bufptr += (int)size; 70 pthread_mutex_unlock(&(self->lock)); 71 72 /* Send signal to thread that buffer has been updated */ 73 pthread_cond_signal(&(self->cond)); 80 #endif 81 82 83 while (size) { 84 pthread_mutex_lock(&(self->lock)); 85 ret = roar_vs_write(self->vss, buf, size, NULL); 86 pthread_mutex_unlock(&(self->lock)); 87 88 if ( ret == -1 ) { 89 ROAR_WARN("roar_plugin_write(self=%p, buf=?, size=?): Can not write data: %s", self, roar_error2str(roar_error)); 90 return -1; 91 } 92 93 size -= ret; 94 buf += ret; 95 96 /* Send signal to thread that buffer has been updated */ 97 ROAR_DBG("roar_plugin_write(self=%p, buf=%p, size=%llu): Send signal", self, buf, (long long unsigned int)size); 98 pthread_cond_signal(&(self->cond)); 99 } 74 100 75 101 return size; … … 83 109 // Attemps to drain the buffer at all times and write to libroar. 84 110 // If there is no data, it will wait for roar_plugin_write() to fill up more data. 85 void * roar_plugin_thread (void * thread_data) {111 void * roar_plugin_thread (void * thread_data) { 86 112 /* We share data between thread and callable functions */ 87 113 struct roar_alsa_pcm *self = thread_data; 88 114 int rc; 115 int err; 116 117 ROAR_DBG("roar_plugin_thread(thread_data=%p) = ?", thread_data); 118 pthread_mutex_unlock(&(self->lock)); // we are now up. 89 119 90 120 /* Plays back data as long as there is data in the buffer. Else, sleep until it can. */ 91 121 /* Two loops! :3 Beware! */ 92 122 while(1) { 123 ROAR_DBG("roar_plugin_thread(thread_data=%p): got woken up.", thread_data); 93 124 while(1) { 94 125 _TEST_CANCEL(); … … 96 127 // We only bother to check after 1 sec of audio has been played, as it might be quite inaccurate in the start of the stream. 97 128 129 // do wee need to lock before this? 130 pthread_mutex_lock(&(self->lock)); 131 ROAR_DBG("roar_plugin_thread(thread_data=%p): Start iterate", thread_data); 132 rc = roar_vs_iterate(self->vss, ROAR_VS_WAIT, &err); 133 ROAR_DBG("roar_plugin_thread(thread_data=%p): Ended iterate", thread_data); 134 pthread_mutex_unlock(&(self->lock)); 135 136 if ( rc == 0 ) { 137 break; 138 } else if ( rc < 0 ) { 139 _TEST_CANCEL(); 140 roar_plugin_reset(self); 141 142 /* Wakes up a potentially sleeping fill_buffer() */ 143 pthread_cond_signal(&(self->cond)); 144 145 /* This thread will not be joined, so detach. */ 146 pthread_detach(pthread_self()); 147 pthread_exit(NULL); 148 } 149 150 pthread_cond_signal(&(self->cond)); 151 152 #if 0 98 153 /* If the buffer is empty or we've stopped the stream. Jump out of this for loop */ 99 154 pthread_mutex_lock(&(self->lock)); … … 139 194 /* Buffer has decreased, signal fill_buffer() */ 140 195 pthread_cond_signal(&(self->cond)); 141 142 } 196 #endif 197 198 } 199 ROAR_DBG("roar_plugin_thread(thread_data=%p): going to sleep again.", thread_data); 143 200 144 201 /* If we're still good to go, sleep. We are waiting for fill_buffer() to fill up some data. */ 145 202 test_quit: 146 203 if ( self->thread_active ) { 147 pthread_cond_signal(&(self->cond)); 204 //struct timespec abstime = {0, 1000*1000*100}; 205 pthread_cond_signal(&(self->cond)); 206 ROAR_DBG("roar_plugin_thread(thread_data=%p): Wating for wakeup", thread_data); 148 207 pthread_mutex_lock(&(self->cond_lock)); 149 208 pthread_cond_wait(&(self->cond), &(self->cond_lock)); … … 159 218 160 219 void roar_plugin_drain(struct roar_alsa_pcm *self) { 220 #if 0 161 221 struct timespec now_tv; 162 222 int64_t temp, temp2; … … 183 243 self->bytes_in_buffer = self->bufptr; 184 244 } 245 #endif 246 ROAR_DBG("roar_plugin_drain(self=%p) = (void)", self); 185 247 } 186 248
Note: See TracChangeset
for help on using the changeset viewer.