/** * @brief Loads a buffer. * * @param buffer Buffer to load. */ static int stream_loadBuffer( ALuint buffer ) { int ret, size, section, result; musicVorbisLock(); /* Make sure music is valid. */ if (music_vorbis.rw == NULL) { musicVorbisUnlock(); return -1; } ret = 0; size = 0; while (size < music_bufSize) { /* fille up the entire data buffer */ result = ov_read_filter( &music_vorbis.stream, /* stream */ &music_buf[size], /* data */ music_bufSize - size, /* amount to read */ VORBIS_ENDIAN, /* big endian? */ 2, /* 16 bit */ 1, /* signed */ §ion, /* current bitstream */ rg_filter, /* filter function */ &music_vorbis ); /* filter parameter */ /* End of file. */ if (result == 0) { if (size == 0) { musicVorbisUnlock(); return -2; } ret = 1; break; } /* Hole error. */ else if (result == OV_HOLE) { musicVorbisUnlock(); WARN("OGG: Vorbis hole detected in music!"); return 0; } /* Bad link error. */ else if (result == OV_EBADLINK) { musicVorbisUnlock(); WARN("OGG: Invalid stream section or corrupt link in music!"); return -1; } size += result; } musicVorbisUnlock(); /* load the buffer up */ soundLock(); alBufferData( buffer, music_vorbis.format, music_buf, size, music_vorbis.info->rate ); soundUnlock(); return ret; }
static void* player_thread(void* _minfo) { ogg_t* minfo = (ogg_t*) _minfo; log_debug("ogg player started"); long current_position_in_ms = 0; long previous_position_in_ms = -1; long guard_position_in_ms = -1; el_bool playing = el_false; post_event(minfo->client_notification, AUDIO_READY, current_position_in_ms); audio_event_t *event; event = audio_event_fifo_dequeue(minfo->player_control); while (event->state != INTERNAL_CMD_DESTROY) { audio_state_t event_state = event->state; long event_position = event->position_in_ms; audio_event_destroy(event); switch (event_state) { case INTERNAL_CMD_LOAD_FILE: { playing = el_false; if (minfo->is_open) { ov_clear(&minfo->vf); fclose(minfo->fh); aodev_close(minfo->ao_handle); } minfo->fh = fopen(minfo->file_or_url, "rb"); if (minfo->fh != NULL) { if (ov_open_callbacks(minfo->fh , &minfo->vf, NULL, 0, OV_CALLBACKS_NOCLOSE) < 0) { fclose(minfo->fh); post_event(minfo->client_notification, AUDIO_NOT_SUPPORTED, -1); minfo->is_open = el_false; } else { minfo->is_open = el_true; minfo->can_seek = ov_seekable(&minfo->vf); minfo->length = (long) (ov_time_total(&minfo->vf, -1) * 1000.0); psem_post(minfo->length_set); minfo->current_section = 0; vorbis_info* vi = ov_info(&minfo->vf, -1); aodev_set_format(minfo->ao_handle, 16, vi->rate, vi->channels); aodev_set_endian(minfo->ao_handle, AO_FMT_LITTLE); aodev_open(minfo->ao_handle); } } else { post_event(minfo->client_notification, AUDIO_IO_ERROR, -1); minfo->is_open = el_false; } current_position_in_ms = 0; guard_position_in_ms = -1; log_debug("Stream initialized"); } break; case INTERNAL_CMD_LOAD_URL: { } break; case INTERNAL_CMD_SEEK: { ov_time_seek_lap(&minfo->vf, ((double) event_position / 1000.0)); } break; case INTERNAL_CMD_PLAY: { playing = el_true; } break; case INTERNAL_CMD_PAUSE: { playing = el_false; } break; case INTERNAL_CMD_GUARD: { guard_position_in_ms = event_position; } break; case INTERNAL_CMD_SET_VOLUME: { double scale = ((double) event_position) / 1000.0; minfo->volume_scale = scale; log_debug2("setting volume to %lf", scale); } break; case INTERNAL_CMD_NONE: break; default: break; } if (guard_position_in_ms >= 0 && current_position_in_ms >= guard_position_in_ms) { guard_position_in_ms = -1; post_event(minfo->client_notification, AUDIO_GUARD_REACHED, current_position_in_ms); } else if (playing) { if (minfo->is_file) { int n = ov_read_filter(&minfo->vf, minfo->buffer, BUFFER_SIZE(minfo), 0, 2, 1, &minfo->current_section, adjust_volume, minfo ); if (n > 0) { aodev_play_buffer(minfo->ao_handle, minfo->buffer, n); //log_debug("buffer played"); double tm = ov_time_tell(&minfo->vf); current_position_in_ms = (long) (tm * 1000.0); if ((current_position_in_ms - previous_position_in_ms) >= STATE_REPORT_THRESHOLD) { post_event(minfo->client_notification, AUDIO_PLAYING, current_position_in_ms); } previous_position_in_ms = current_position_in_ms; } else { post_event(minfo->client_notification, AUDIO_EOS, current_position_in_ms); playing = el_false; } } else { // Stream playing post_event(minfo->client_notification, AUDIO_STATE_ERROR, -1); playing = el_false; } } if (playing) { if (audio_event_fifo_peek(minfo->player_control) != NULL) { event = audio_event_fifo_dequeue(minfo->player_control); } else { event = (audio_event_t*) mc_malloc(sizeof(audio_event_t)); event->state = INTERNAL_CMD_NONE; event->position_in_ms = -1; } } else { event = audio_event_fifo_dequeue(minfo->player_control); } } // destroy event received audio_event_destroy(event); // exit thread return NULL; }