mplay.mp3

Controllable music player (mp3)
git clone https://git.sinitax.com/sinitax/mplay.mp3
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

commit 90f73476fb541f86d1e93625d5266f66b198d9a7
parent 6c5b8a2c45d54d2acacd224300f1c84d1c145d2c
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sun, 10 Mar 2024 00:01:23 +0100

Fix piped buffering, prevent holding lock in get_line

Diffstat:
Mmplay.mp3.c | 51+++++++++++++++++++++++++++++++++++++--------------
1 file changed, 37 insertions(+), 14 deletions(-)

diff --git a/mplay.mp3.c b/mplay.mp3.c @@ -88,7 +88,9 @@ static bool headless = false; static bool verbose = false; static bool istty = false; -__attribute__((noreturn)) static void +static void +__attribute__((noreturn)) +__attribute__((format(printf, 1, 2))) die(const char *fmt, ...) { va_list ap; @@ -129,7 +131,7 @@ get_line(char *buf, int size) { char *c; - putc('>', stderr); + if (istty) putc('>', stderr); if (istty) term_set_canonical(); fgets(buf, size, stdin); if ((c = strchr(buf, '\n'))) *c = '\0'; @@ -376,10 +378,16 @@ user_time(void) } static void -cmd_setvol(double vol) +cmd_setvol(double vol, double delta) { pa_operation *op; + pa_threaded_mainloop_lock(pa_mloop); + + if (delta != 0) { + vol = user_vol() + delta; + } + update_sink_input_info(); pa_cvolume_set(&pa_strm_sink.volume, 2, (pa_volume_t) (vol * PA_VOLUME_NORM / 100.F)); @@ -393,14 +401,22 @@ cmd_setvol(double vol) mplay_status(MPLAY_INFO_VOLUME, "%02.2f", (double) pa_cvolume_avg(&pa_strm_sink.volume) * 100.f / (double) PA_VOLUME_NORM); + + pa_threaded_mainloop_unlock(pa_mloop); } static void -cmd_seek(double time_sec) +cmd_seek(double time_sec, double delta) { size_t sample_pos; pa_operation *op; + pa_threaded_mainloop_lock(pa_mloop); + + if (delta != 0) { + time_sec = user_time() + delta; + } + if (time_sec < 0) time_sec = 0; sample_pos = (size_t) (time_sec * mp3d.channels * mp3d.rate); decoder_seek(sample_pos); @@ -410,6 +426,8 @@ cmd_seek(double time_sec) mp3d.seek = true; mplay_status(MPLAY_INFO_SEEK, "%02.2f", user_time()); + + pa_threaded_mainloop_unlock(pa_mloop); } static void @@ -417,21 +435,29 @@ cmd_playpause(void) { pa_operation *op; + pa_threaded_mainloop_lock(pa_mloop); + mp3d.pause ^= 1; op = pa_stream_cork(pa_strm, mp3d.pause, NULL, NULL); pa_operation_unref(op); mplay_status(MPLAY_INFO_PAUSE, "%i", mp3d.pause); + + pa_threaded_mainloop_unlock(pa_mloop); } static void cmd_status(void) { + pa_threaded_mainloop_lock(pa_mloop); + update_sink_input_info(); mplay_status(MPLAY_INFO_STATUS, "volume=%02.2f,time=%02.2f,pause=%i", user_vol(), user_time(), mp3d.pause); + + pa_threaded_mainloop_unlock(pa_mloop); } static bool @@ -443,8 +469,6 @@ key_input(void) while ((key = mplay_getkey()) == MPLAY_KEY_EOF); - pa_threaded_mainloop_lock(pa_mloop); - switch (mplay_action(key)) { case MPLAY_ACTION_VOLUME: get_line(linebuf, sizeof(linebuf)); @@ -453,13 +477,13 @@ key_input(void) mplay_status(MPLAY_INFO_VOLUME, "fail:bad float"); break; } - cmd_setvol(fval); + cmd_setvol(fval, 0); break; case MPLAY_ACTION_VOLUME_UP: - cmd_setvol(user_vol() + 5); + cmd_setvol(0, 5); break; case MPLAY_ACTION_VOLUME_DOWN: - cmd_setvol(user_vol() - 5); + cmd_setvol(0, -5); break; case MPLAY_ACTION_SEEK: get_line(linebuf, sizeof(linebuf)); @@ -468,13 +492,13 @@ key_input(void) mplay_status(MPLAY_INFO_SEEK, "fail:bad float"); break; } - cmd_seek(fval); + cmd_seek(fval, 0); break; case MPLAY_ACTION_SEEK_BWD: - cmd_seek(user_time() - 5); + cmd_seek(0, -5); break; case MPLAY_ACTION_SEEK_FWD: - cmd_seek(user_time() + 5); + cmd_seek(0, 5); break; case MPLAY_ACTION_PAUSE: cmd_playpause(); @@ -487,8 +511,6 @@ key_input(void) break; } - pa_threaded_mainloop_unlock(pa_mloop); - return true; } @@ -498,6 +520,7 @@ input_worker(void *arg) input_worker_alive = true; setvbuf(stdin, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); if (istty) {