mplay

Controllable music player
git clone https://git.sinitax.com/sinitax/mplay
Log | Files | Refs | sfeed.txt

commit aab4376554c0930e82a02c02f6bc778c15501cb2
parent fd2eab5578b99ba0bb5f32a8f08dbd9fbeb9a9b4
Author: Louis Burda <quent.burda@gmail.com>
Date:   Sat, 17 Dec 2022 15:42:05 +0100

Improved input key handling

Diffstat:
Msrc/mplay.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 108 insertions(+), 22 deletions(-)

diff --git a/src/mplay.c b/src/mplay.c @@ -1,3 +1,4 @@ +#include <pulse/introspect.h> #include <pulse/volume.h> #define MINIMP3_IMPLEMENTATION #include "minimp3.h" @@ -17,6 +18,15 @@ #include <stdio.h> #include <stdlib.h> +enum { + KEY_NONE = 0, + KEY_BRK = 3, + KEY_LEFT = 0x100, + KEY_RIGHT, + KEY_UP, + KEY_DOWN, +}; + #define ERR(...) err(1, __VA_ARGS__) #define ERRX(...) errx(1, __VA_ARGS__) #define PA_CTX_ERR(ctx, fmt, ...) do { \ @@ -80,6 +90,9 @@ map_file(const char *path, size_t *len) if (fstat(fd, &attr)) ERR("fstat %s", path); + if ((attr.st_mode & S_IFMT) == S_IFDIR) + ERRX("not a file: %s", path); + buf = mmap(NULL, attr.st_size, PROT_READ, MAP_PRIVATE, fd, 0); if (!buf) ERR("mmap %s", path); @@ -102,6 +115,8 @@ pa_stream_write_callback(pa_stream *stream, size_t requested, void *data) while (remaining > 0 && mp3d.left > 0) { cnt = mp3dec_decode_frame(&mp3d.dec, mp3d.pos, mp3d.left, samples, &info); + if (mp3d.pos == audiofile.data && !cnt) + ERRX("Invalid mp3 input file"); if (!cnt && !info.frame_bytes) break; mp3d.pos += info.frame_bytes; @@ -113,6 +128,9 @@ pa_stream_write_callback(pa_stream *stream, size_t requested, void *data) NULL, 0, PA_SEEK_RELATIVE); remaining -= info.frame_bytes; } + + if (!mp3d.left) + pa_mainloop_quit(pa_mloop, 0); } void @@ -125,10 +143,10 @@ pa_stream_state_callback(pa_stream *stream, void *data) case PA_STREAM_READY: pa_stream_cork(stream, 0, NULL, NULL); break; - case PA_STREAM_UNCONNECTED: - printf("DISCONECTED\n"); + case PA_STREAM_TERMINATED: pa_mainloop_quit(pa_mloop, 0); break; + case PA_STREAM_UNCONNECTED: case PA_STREAM_CREATING: default: break; @@ -163,9 +181,12 @@ pa_state_callback(pa_context *pa_ctx, void *data) ret = pa_stream_connect_playback(pa_strm, NULL, &pa_buf, pa_stream_flags, NULL, NULL); - if (ret) PA_ERRX("pa_stream_connect_playback"); + if (ret) PA_ERRX("pa_stream_connect_playback failed"); break; + case PA_CONTEXT_TERMINATED: + pa_mainloop_quit(pa_mloop, 0); + break; case PA_CONTEXT_CONNECTING: case PA_CONTEXT_UNCONNECTED: default: @@ -191,12 +212,81 @@ pa_worker(void *arg) return NULL; } +int +getkey_esc(void) +{ + char c; + + c = getchar(); + switch (c) { + case 'A': + return KEY_UP; + case 'B': + return KEY_DOWN; + case 'C': + return KEY_DOWN; + case 'D': + return KEY_DOWN; + default: + return KEY_NONE; + } +} + +void +cmd_inc_volume(void) +{ + pa_context_get_sink_input_info(pa_ctx, + pa_stream_get_index(pa_strm), + pa_sink_input_info_callback, NULL); + pa_cvolume_inc(&pa_strm_info.volume, 65536 / 20); + if (pa_cvolume_avg(&pa_strm_info.volume) > 2 * PA_VOLUME_NORM) + pa_cvolume_set(&pa_strm_info.volume, 2, 2 * PA_VOLUME_NORM); + pa_context_set_sink_input_volume(pa_ctx, + pa_stream_get_index(pa_strm), + &pa_strm_info.volume, NULL, NULL); + printf("VOLUME: %02.f\n", + pa_cvolume_avg(&pa_strm_info.volume) + * 100.f / PA_VOLUME_NORM); +} + +void +cmd_dec_volume(void) +{ + pa_context_get_sink_input_info(pa_ctx, + pa_stream_get_index(pa_strm), + pa_sink_input_info_callback, NULL); + pa_cvolume_dec(&pa_strm_info.volume, 65536 / 20); + pa_context_set_sink_input_volume(pa_ctx, + pa_stream_get_index(pa_strm), + &pa_strm_info.volume, NULL, NULL); + printf("VOLUME: %02.f\n", + pa_cvolume_avg(&pa_strm_info.volume) + * 100.f / PA_VOLUME_NORM); +} + +int +getkey(void) +{ + char c; + + c = getchar(); + if (c == 0x1b) { + c = getchar(); + if (c == '[') { + return getkey_esc(); + } else { + return KEY_NONE; + } + } else { + return c; + } +} + void * input_worker(void *arg) { - pa_cvolume vol; struct termios old, new; - char c; + int key; if (tcgetattr(0, &old)) ERR("tcgetattr"); @@ -205,27 +295,23 @@ input_worker(void *arg) new.c_iflag |= BRKINT; new.c_iflag &= ~IGNBRK; new.c_lflag &= ~ICANON; + new.c_lflag &= ~ECHO; if (tcsetattr(0, TCSANOW, &new)) ERR("tcsetattr"); - while ((c = getchar())) { - if (c == '+') { - pa_context_get_sink_input_info(pa_ctx, - pa_stream_get_index(pa_strm), - pa_sink_input_info_callback, NULL); - pa_cvolume_inc(&pa_strm_info.volume, 1); - pa_context_set_sink_input_volume(pa_ctx, - pa_stream_get_index(pa_strm), - &pa_strm_info.volume, NULL, NULL); - } else if (c == '-') { - pa_context_get_sink_input_info(pa_ctx, - pa_stream_get_index(pa_strm), - pa_sink_input_info_callback, NULL); - pa_cvolume_dec(&pa_strm_info.volume, 1); - pa_context_set_sink_input_volume(pa_ctx, - pa_stream_get_index(pa_strm), - &pa_strm_info.volume, NULL, NULL); + while (true) { + while (!(key = getkey())); + if (key == '+' || key == KEY_UP) { + cmd_inc_volume(); + } else if (key == '-' || key == KEY_DOWN) { + cmd_dec_volume(); + } else if (key == KEY_LEFT) { + + } else if (key == KEY_RIGHT) { + + } else { + printf("Unbound key: %i\n", key); } }