off_t term_control(mpg123_handle *fr, out123_handle *ao) { offset = 0; debug2("control for frame: %li, enable: %i", (long)mpg123_tellframe(fr), term_enable); if(!term_enable) return 0; if(paused) { /* pause_cycle counts the remaining frames _after_ this one, thus <0, not ==0 . */ if(--pause_cycle < 0) pause_recycle(fr); } do { off_t old_offset = offset; term_handle_input(fr, ao, stopped|seeking); if((offset < 0) && (-offset > framenum)) offset = - framenum; if(param.verbose && offset != old_offset) print_stat(fr,offset,ao); } while (!intflag && stopped); /* Make the seeking experience with buffer less annoying. No sound during seek, but at least it is possible to go backwards. */ if(offset) { if((offset = mpg123_seek_frame(fr, offset, SEEK_CUR)) >= 0) debug1("seeked to %li", (long)offset); else error1("seek failed: %s!", mpg123_strerror(fr)); /* Buffer resync already happened on un-stop? */ /* if(param.usebuffer) audio_drop(ao);*/ } return 0; }
int mpeg_tell(int fd, int *pos, int *len) { int rv = -1; if((handle != NULL) && (fd != -1)) { off_t sample_off = 0; off_t frame_off = 0; double time_off = 0; double time_per_frame = 0; int samples_per_frame = 0; time_per_frame = mpg123_tpf(handle->mh); samples_per_frame = mpg123_spf(handle->mh); /* Determine current position */ frame_off = mpg123_tellframe(handle->mh); time_off = frame_off * (double)time_per_frame; *pos = (int) time_off; /* Determine track duration */ sample_off = mpg123_length(handle->mh); if(samples_per_frame != 0) { frame_off = sample_off / samples_per_frame; time_off = frame_off * (double)time_per_frame; *len = (int) time_off; } rv = 0; } return rv; }
off_t term_control(mpg123_handle *fr, audio_output_t *ao) { offset = 0; debug1("control for frame: %li", (long)mpg123_tellframe(fr)); if(!term_enable) return 0; if(paused) { /* pause_cycle counts the remaining frames _after_ this one, thus <0, not ==0 . */ if(--pause_cycle < 0) { pause_recycle(fr); if(param.usebuffer) { while(paused && xfermem_get_usedspace(buffermem)) { buffer_ignore_lowmem(); term_handle_input(fr, ao, TRUE); } /* Undo the cycling offset if we are done with cycling. */ if(!paused) pause_uncycle(); } } } do { term_handle_input(fr, ao, stopped|seeking); if((offset < 0) && (-offset > framenum)) offset = - framenum; if(param.verbose && offset != 0) print_stat(fr,offset,0); } while (stopped); /* Make the seeking experience with buffer less annoying. No sound during seek, but at least it is possible to go backwards. */ if(offset) { if((offset = mpg123_seek_frame(fr, offset, SEEK_CUR)) >= 0) debug1("seeked to %li", (long)offset); else error1("seek failed: %s!", mpg123_strerror(fr)); /* Buffer resync already happened on un-stop? */ /* if(param.usebuffer) buffer_resync();*/ } return 0; }
static size_t dec_mp3(struct file_type *ft, size_t out_frames, void *out_buf) { size_t cdone = 0; struct mp3_format *mp3 = (struct mp3_format *)ft; int ret; do { size_t bdone; ret = mpg123_read(mp3->mh, out_buf, (out_frames - cdone) * 4, &bdone); cdone += bdone / 4; } while ((cdone < out_frames) && (ret != MPG123_DONE) && (ret <= 0)); ft->position = (volatile int)(mpg123_tellframe(mp3->mh) * mp3->tpf); return cdone; }
JNIEXPORT float JNICALL Java_com_axelby_mp3decoders_MPG123_getPosition (JNIEnv *env, jclass c, jlong handle) { MP3File *mp3 = (MP3File *)handle; return mpg123_tellframe(mp3->handle) * mp3->secs_per_frame; }
VALUE rb_mpg123_tellframe(VALUE self) { return INT2FIX(mpg123_tellframe(DATA_PTR(self))); }
void* player_thread(void* _mp3_info) { log_debug("player thread started"); mp3_t* mp3_info = (mp3_t* ) _mp3_info; long current_position_in_ms = 0; long previous_position_in_ms = -1; long guard_position_in_ms = -1; el_bool playing = el_false; pthread_t thread_id; int no_count = 0; post_event(mp3_info->client_notification, AUDIO_READY, current_position_in_ms); audio_event_t *event; event = audio_event_fifo_dequeue(mp3_info->player_control); while (event->state != INTERNAL_CMD_DESTROY) { if (event->state != INTERNAL_CMD_NONE) { log_debug4("event = %s, %ld, %s", audio_event_name(event->state), event->position_in_ms, mp3_info->file_or_url); } 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; // Stop stream, if playing if (!mp3_info->is_file) { mp3_info->continue_streaming = el_false; psem_wait(mp3_info->stream_ready); } if (mp3_info->is_open) { mpg123_close(mp3_info->handle); aodev_close(mp3_info->ao_handle); } mpg123_open(mp3_info->handle, mp3_info->file_or_url); mpg123_getformat(mp3_info->handle, &mp3_info->rate, &mp3_info->channels, &mp3_info->encoding); mp3_info->buffer_size = mpg123_outblock(mp3_info->handle); mc_free(mp3_info->buffer); mp3_info->buffer = mc_malloc(mp3_info->buffer_size * sizeof(char) ); int bytes_per_sample = get_encsize(mp3_info->encoding); aodev_set_format(mp3_info->ao_handle, bytes_per_sample * 8, mp3_info->rate, mp3_info->channels); aodev_open(mp3_info->ao_handle); mp3_info->is_open = el_true; mp3_info->is_file = el_true; mp3_info->can_seek = el_true; current_position_in_ms = 0; guard_position_in_ms = -1; { off_t l = mpg123_length(mp3_info->handle); if (l == MPG123_ERR) { mp3_info->length = -1; } else { mp3_info->length = (l * 1000) / mp3_info->rate; } psem_post(mp3_info->length_set); } } break; case INTERNAL_CMD_LOAD_URL: { playing = el_false; log_debug2("loading url %s", mp3_info->file_or_url); // Wait for feeding streams to end if (!mp3_info->is_file) { mp3_info->continue_streaming = el_false; psem_wait(mp3_info->stream_ready); } mp3_info->is_file = el_false; log_debug("current stream ended"); if (mp3_info->is_open) { mpg123_close(mp3_info->handle); aodev_close(mp3_info->ao_handle); mp3_info->is_open = el_false; } log_debug("aodev closed"); mpg123_open_feed(mp3_info->handle); log_debug("feed opened"); pthread_create(&thread_id, NULL, stream_thread, mp3_info); log_debug("stream thread started"); mp3_info->is_open = el_true; mp3_info->can_seek = el_false; current_position_in_ms = 0; guard_position_in_ms = -1; mp3_info->length = 0; mp3_info->continue_streaming = el_true; psem_post(mp3_info->length_set); } break; case INTERNAL_CMD_SEEK: { off_t pos = mpg123_timeframe(mp3_info->handle, (event_position / 1000.0)); mpg123_seek_frame(mp3_info->handle, pos, SEEK_SET); } 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 volume = ((double) event_position) / 1000.0; mpg123_volume(mp3_info->handle, volume); } case INTERNAL_CMD_NONE: break; default: break; } //log_debug3("guard = %d, playing = %d", guard_position_in_ms, playing); if (guard_position_in_ms >= 0 && current_position_in_ms >= guard_position_in_ms) { guard_position_in_ms = -1; post_event(mp3_info->client_notification, AUDIO_GUARD_REACHED, current_position_in_ms); } else if (playing) { if (mp3_info->is_file) { size_t bytes; int res = mpg123_read(mp3_info->handle, mp3_info->buffer, mp3_info->buffer_size, &bytes); if (res == MPG123_OK) { aodev_play_buffer(mp3_info->ao_handle, mp3_info->buffer, bytes); off_t frame = mpg123_tellframe(mp3_info->handle); double time_per_frame = (mpg123_tpf(mp3_info->handle)*1000.0); //static int prt = 1; //if (prt) { printf("tpf=%.6lf\n",time_per_frame);prt=0; } current_position_in_ms = (long) (frame * time_per_frame); // 1 frame is about 26 milliseconds if (previous_position_in_ms == -1) previous_position_in_ms = current_position_in_ms; if ((current_position_in_ms - previous_position_in_ms) >= STATE_REPORT_THRESHOLD) { post_event(mp3_info->client_notification, AUDIO_PLAYING, current_position_in_ms); } previous_position_in_ms = current_position_in_ms; } else if (res == MPG123_DONE) { post_event(mp3_info->client_notification, AUDIO_EOS, current_position_in_ms); playing = el_false; } else { post_event(mp3_info->client_notification, AUDIO_STATE_ERROR, current_position_in_ms); playing = el_false; } } else { // Stream playing if (mp3_stream_fifo_peek(mp3_info->stream_fifo) != NULL) { el_bool go_on = el_true; while (go_on && mp3_stream_fifo_peek(mp3_info->stream_fifo) != NULL) { memblock_t* blk = mp3_stream_fifo_dequeue(mp3_info->stream_fifo); mpg123_feed(mp3_info->handle, (const unsigned char*) memblock_as_str(blk), memblock_size(blk)); memblock_destroy(blk); size_t done; int err; unsigned char *audio; off_t frame_offset; do { err = mpg123_decode_frame(mp3_info->handle, &frame_offset, &audio, &done); switch(err) { case MPG123_NEW_FORMAT: mpg123_getformat(mp3_info->handle, &mp3_info->rate, &mp3_info->channels, &mp3_info->encoding); if (aodev_is_open(mp3_info->ao_handle)) { aodev_close(mp3_info->ao_handle); } aodev_set_format(mp3_info->ao_handle, get_encsize(mp3_info->encoding) * 8, mp3_info->rate, mp3_info->channels); aodev_open(mp3_info->ao_handle); break; case MPG123_OK: //log_debug2("playing buffer %d", done); aodev_play_buffer(mp3_info->ao_handle, audio, done); off_t frame = mpg123_tellframe(mp3_info->handle); double time_per_frame = (mpg123_tpf(mp3_info->handle)*1000.0); current_position_in_ms = (long) (frame * time_per_frame); // 1 frame is about 26 milliseconds if (previous_position_in_ms == -1) previous_position_in_ms = current_position_in_ms; if ((current_position_in_ms - previous_position_in_ms) >= STATE_REPORT_THRESHOLD) { post_event(mp3_info->client_notification, AUDIO_PLAYING, current_position_in_ms); } previous_position_in_ms = current_position_in_ms; go_on = el_false; break; case MPG123_NEED_MORE: break; default: break; } } while (done > 0); } } else { // no streaming data, prevent race conditions // sleep for a small time (50 ms); no_count += 1; if (no_count > 10) { post_event(mp3_info->client_notification, AUDIO_BUFFERING, current_position_in_ms); } sleep_ms(50); } } } if (playing) { if (audio_event_fifo_peek(mp3_info->player_control) != NULL) { event = audio_event_fifo_dequeue(mp3_info->player_control); } else { event = (audio_event_t*) mc_malloc(sizeof(audio_event_t)); event->state = INTERNAL_CMD_NONE; event->position_in_ms = -1; } } else { //log_debug("waiting for next event"); event = audio_event_fifo_dequeue(mp3_info->player_control); } } // destroy event received log_debug("destroy event received"); // Kill playing streams if (mp3_info->streaming) { mp3_info->continue_streaming = el_false; psem_wait(mp3_info->stream_ready); } audio_event_destroy(event); // exit thread return NULL; }
static cxOff cxMp3StreamPosition(cxAny stream) { cxMp3Stream this = stream; return (cxOff)mpg123_tellframe(this->mh); }
void SaveStatus() { char statusFile[MAX_PATH] = {0}; char *q; int ret; off_t frameNumber = 0; char frameNumBuffer[128] = {0}; GetModuleFileName(NULL, statusFile, sizeof(statusFile)); q = strrchr(statusFile, '\\'); if(q == NULL) { return; } q++; *q = '\0'; strcat(statusFile, STATUS_FILE); if(stopFlag) { if(WritePrivateProfileString("state", "stop", "1", statusFile) == FALSE) { return; } } else { if(WritePrivateProfileString("state", "stop", "0", statusFile) == FALSE) { return; } } if(pauseFlag) { if(WritePrivateProfileString("state", "pause", "1", statusFile) == FALSE) { return; } } else { if(WritePrivateProfileString("state", "pause", "0", statusFile) == FALSE) { return; } } if(WritePrivateProfileString("music", "name", fileInfo.cFileName, statusFile) == FALSE) { return; } if(stopFlag != TRUE) { frameNumber = mpg123_tellframe(mh); } _snprintf(frameNumBuffer, sizeof(frameNumBuffer), "%d", frameNumber); if(WritePrivateProfileString("music", "frame", frameNumBuffer, statusFile) == FALSE) { return; } }