diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index aac180159..5fd03debd 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -384,7 +384,11 @@ int audio_init(struct state_audio **ret, cfg = delim + 1; } - int ret = audio_playback_init(device, cfg, &s->audio_playback_device); + struct audio_playback_opts opts; + snprintf_ch(opts.cfg, "%s", cfg); + opts.parent = s->audio_receiver_module.get(); + const int ret = audio_playback_init(device, &opts, + &s->audio_playback_device); free(device); if (ret != 0) { retval = ret; diff --git a/src/audio/audio_playback.c b/src/audio/audio_playback.c index 450f40d39..0030ff1a7 100644 --- a/src/audio/audio_playback.c +++ b/src/audio/audio_playback.c @@ -69,11 +69,11 @@ void audio_playback_help(bool full) list_modules(LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION, full); } -int audio_playback_init(const char *device, const char *cfg, struct state_audio_playback **state) +int +audio_playback_init(const char *device, const struct audio_playback_opts *opts, + struct state_audio_playback **state) { - struct state_audio_playback *s; - - s = calloc(1, sizeof(struct state_audio_playback)); + struct state_audio_playback *s= calloc(1, sizeof(*s)); gettimeofday(&s->t0, NULL); s->funcs = load_library(device, LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION); @@ -83,7 +83,7 @@ int audio_playback_init(const char *device, const char *cfg, struct state_audio_ } strncpy(s->name, device, sizeof s->name - 1); - s->state = s->funcs->init(cfg); + s->state = s->funcs->init(opts); if(!s->state) { log_msg(LOG_LEVEL_ERROR, "Error initializing audio playback.\n"); @@ -105,8 +105,9 @@ int audio_playback_init(const char *device, const char *cfg, struct state_audio_ struct state_audio_playback *audio_playback_init_null_device(void) { + const struct audio_playback_opts opts = { 0 }; struct state_audio_playback *device = NULL; - int ret = audio_playback_init("none", "", &device); + int ret = audio_playback_init("none", &opts, &device); if (ret != 0) { log_msg(LOG_LEVEL_ERROR, "Unable to initialize null audio playback: %d\n", ret); } diff --git a/src/audio/audio_playback.h b/src/audio/audio_playback.h index 7724b148e..ee5ba05ba 100644 --- a/src/audio/audio_playback.h +++ b/src/audio/audio_playback.h @@ -38,18 +38,22 @@ #ifndef AUDIO_AUDIO_PLAYBACK_H_316AA23B_3EFF_4150_83D2_24A2295CB74A #define AUDIO_AUDIO_PLAYBACK_H_316AA23B_3EFF_4150_83D2_24A2295CB74A +#ifndef __cplusplus +#include +#endif // ! defined __cplusplus + #include "../types.h" +#include "utils/macros.h" // for STR_LEN struct audio_desc; struct audio_frame; +struct module; #ifdef __cplusplus extern "C" { -#else -#include #endif -#define AUDIO_PLAYBACK_ABI_VERSION 11 +#define AUDIO_PLAYBACK_ABI_VERSION 12 /** @anchor audio_playback_ctl_reqs * @name Audio playback control requests @@ -80,9 +84,14 @@ extern "C" { #define AUDIO_PLAYBACK_PUT_NETWORK_DEVICE 3 /// @} +struct audio_playback_opts { + char cfg[STR_LEN]; + struct module *parent; +}; + struct audio_playback_info { device_probe_func probe; - void *(*init)(const char *cfg); ///< @param cfg is not NULL + void *(*init)(const struct audio_playback_opts *opts); void (*write)(void *state, const struct audio_frame *frame); /** Returns device supported format that matches best with propsed audio desc */ bool (*ctl)(void *state, int request, void *data, size_t *len); @@ -97,8 +106,9 @@ void audio_playback_init_devices(void); /** * @see display_init */ -int audio_playback_init(const char *device, const char *cfg, - struct state_audio_playback **); +int audio_playback_init(const char *device, + const struct audio_playback_opts *opts, + struct state_audio_playback **state); struct state_audio_playback *audio_playback_init_null_device(void); /** diff --git a/src/audio/filter/playback.cpp b/src/audio/filter/playback.cpp index cd6c92b7e..718bb792b 100644 --- a/src/audio/filter/playback.cpp +++ b/src/audio/filter/playback.cpp @@ -35,23 +35,21 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" -#endif /* HAVE_CONFIG_H */ - +#include // for printf #include #include -#include "debug.h" #include "module.h" #include "audio/audio_filter.h" -#include "audio/types.h" #include "audio/audio_playback.h" +#include "audio/types.h" #include "lib_common.h" -#include "utils/string_view_utils.hpp" +#include "messaging.h" // for free_message, new_response +#include "utils/macros.h" // for snprintf_ch #include "utils/misc.h" +#include "utils/string_view_utils.hpp" + +struct state_audio_playback; namespace{ struct Playback_dev_deleter{ void operator()(state_audio_playback *p){ audio_playback_done(p); } }; @@ -87,7 +85,11 @@ static af_result_code parse_cfg(state_playback *s, std::string_view cfg){ auto dev = std::string(tok); auto dev_cfg = std::string(tokenize(cfg, ':')); - int ret = audio_playback_init(dev.c_str(), dev_cfg.c_str(), out_ptr(s->playback_dev)); + struct audio_playback_opts opts; + snprintf_ch(opts.cfg, "%s", dev_cfg.c_str()); + opts.parent = nullptr; + + int ret = audio_playback_init(dev.c_str(), &opts, out_ptr(s->playback_dev)); return ret == 0 ? AF_OK : AF_FAILURE; } @@ -111,9 +113,9 @@ static af_result_code configure(void *state, s->ch_count = in_ch_count; s->sample_rate = in_sample_rate; - if (audio_playback_reconfigure(s->playback_dev.get(), s->bps * 8, + if (!audio_playback_reconfigure(s->playback_dev.get(), s->bps * 8, s->ch_count, - s->sample_rate) != TRUE) { + s->sample_rate)) { return AF_FAILURE; } diff --git a/src/audio/playback/alsa.c b/src/audio/playback/alsa.c index ce1050d2d..3263f0d32 100644 --- a/src/audio/playback/alsa.c +++ b/src/audio/playback/alsa.c @@ -842,10 +842,15 @@ init_local_config_with_workaround(char const * pcm_node_name) ADD_TO_PARAM("alsa-playback-api", "* alsa-playback-api={thread|sync|async}\n" " ALSA API.\n"); -static void * audio_play_alsa_init(const char *cfg) +static void * +audio_play_alsa_init(const struct audio_playback_opts *opts) { + if (strcmp(opts->cfg, "help") == 0) { + audio_play_alsa_help(); + return INIT_NOERR; + } + int rc; - const char *name; struct state_alsa_playback *s = calloc(1, sizeof(struct state_alsa_playback)); @@ -879,24 +884,13 @@ static void * audio_play_alsa_init(const char *cfg) log_msg(LOG_LEVEL_WARNING, MOD_NAME "Async API is experimental, in case of problems use either \"thread\" or \"sync\" API\n"); } - if (strlen(cfg) > 0) { - if(strcmp(cfg, "help") == 0) { - audio_play_alsa_help(); - free(s); - return INIT_NOERR; - } - name = cfg; - } else { - if (is_default_pulse()) { - name = "pulse"; - } else { - name = "default"; - } + const char *name = is_default_pulse() ? "pulse" : "default"; + if (strlen(opts->cfg) > 0) { + name = opts->cfg; } - char device[1024] = "pcm."; - - strncat(device, name, sizeof(device) - strlen(device) - 1); + char device[STR_LEN + 4]; + snprintf_ch(device, "pcm.%s", name); if (s->playback_mode == SYNC) { s->local_config = init_local_config_with_workaround(device); diff --git a/src/audio/playback/coreaudio.cpp b/src/audio/playback/coreaudio.cpp index 561072ab4..c421e8233 100644 --- a/src/audio/playback/coreaudio.cpp +++ b/src/audio/playback/coreaudio.cpp @@ -403,9 +403,14 @@ static void audio_play_ca_help() deleter ? deleter(available_devices) : free(available_devices); } - -static void * audio_play_ca_init(const char *cfg) +static void * +audio_play_ca_init(const struct audio_playback_opts *opts) { + if (strcmp(opts->cfg, "help") == 0) { + audio_play_ca_help(); + return INIT_NOERR; + } + OSStatus ret = noErr; AudioComponent comp; AudioComponentDescription comp_desc; @@ -455,22 +460,17 @@ static void * audio_play_ca_init(const char *cfg) goto error; } - if (strcmp(cfg, "help") == 0) { - audio_play_ca_help(); - delete s; - return INIT_NOERR; - } - if (strlen(cfg) > 0) { + if (strlen(opts->cfg) > 0) { try { - device = stoi(cfg); + device = stoi(opts->cfg); } catch (std::invalid_argument &e) { - device = audio_ca_get_device_by_name(cfg, CA_DIR); + device = audio_ca_get_device_by_name(opts->cfg, CA_DIR); if (device == UINT_MAX) { log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong device index " "or unrecognized name \"%s\"!\n", - cfg); + opts->cfg); goto error; } } diff --git a/src/audio/playback/decklink.cpp b/src/audio/playback/decklink.cpp index d9cbd397a..3df2e3ea7 100644 --- a/src/audio/playback/decklink.cpp +++ b/src/audio/playback/decklink.cpp @@ -182,8 +182,14 @@ static void audio_play_decklink_help() } } -static void *audio_play_decklink_init(const char *cfg) +static void * +audio_play_decklink_init(const struct audio_playback_opts *opts) { + if (strcmp(opts->cfg, "help") == 0) { + audio_play_decklink_help(); + return INIT_NOERR; + } + struct state_decklink *s = NULL; IDeckLinkIterator* deckLinkIterator; HRESULT result; @@ -202,15 +208,11 @@ static void *audio_play_decklink_init(const char *cfg) s->magic = DECKLINK_MAGIC; s->audio_consumer_levels = -1; - if (strlen(cfg) == 0) { + if (strlen(opts->cfg) == 0) { cardIdx = 0; fprintf(stderr, "Card number unset, using first found (see -r decklink:help)!\n"); - } else if (strcmp(cfg, "help") == 0) { - audio_play_decklink_help(); - free(s); - return INIT_NOERR; } else { - char *tmp = strdup(cfg); + char *tmp = strdup(opts->cfg); char *item, *save_ptr; item = strtok_r(tmp, ":", &save_ptr); if (item) { @@ -224,10 +226,10 @@ static void *audio_play_decklink_init(const char *cfg) } item = strtok_r(NULL, ":", &save_ptr); if (item) { - cardIdx = atoi(cfg); + cardIdx = atoi(opts->cfg); } } else { - cardIdx = atoi(cfg); + cardIdx = atoi(opts->cfg); } } free(tmp); diff --git a/src/audio/playback/dummy.c b/src/audio/playback/dummy.c index c82b39836..afae216ba 100644 --- a/src/audio/playback/dummy.c +++ b/src/audio/playback/dummy.c @@ -73,17 +73,18 @@ static void audio_play_dummy_help(void) color_printf("\t" TBOLD("debug") " - audio print frame TS + len\n"); } -static void * audio_play_dummy_init(const char *cfg) +static void * +audio_play_dummy_init(const struct audio_playback_opts *opts) { struct state_dummy_aplay *s = calloc(1, sizeof *s); - if (strcmp(cfg, "debug") == 0) { + if (strcmp(opts->cfg, "debug") == 0) { s->debug = true; - } else if (strcmp(cfg, "help") == 0) { + } else if (strcmp(opts->cfg, "help") == 0) { audio_play_dummy_help(); free(s); return INIT_NOERR; - } else if (strlen(cfg) > 0) { - MSG(ERROR, "Wrong option: %s\n", cfg); + } else if (strlen(opts->cfg) > 0) { + MSG(ERROR, "Wrong option: %s\n", opts->cfg); free(s); return NULL; } diff --git a/src/audio/playback/dump.cpp b/src/audio/playback/dump.cpp index 6eabfcea8..39795a516 100644 --- a/src/audio/playback/dump.cpp +++ b/src/audio/playback/dump.cpp @@ -71,16 +71,15 @@ static void audio_play_dump_help() { "\n"); } -static void * audio_play_dump_init(const char *cfg){ +static void * audio_play_dump_init(const struct audio_playback_opts *opts){ + if (strcmp(opts->cfg, "help") == 0) { + audio_play_dump_help(); + return INIT_NOERR; + } struct audio_dump_state *s = new audio_dump_state(); - if (strlen(cfg) > 0) { - if (strcmp(cfg, "help") == 0) { - audio_play_dump_help(); - delete s; - return INIT_NOERR; - } - s->filename = cfg; + if (strlen(opts->cfg) > 0) { + s->filename = opts->cfg; } else { s->filename = "audio_dump"; } diff --git a/src/audio/playback/jack.c b/src/audio/playback/jack.c index d2efaa156..69038073c 100644 --- a/src/audio/playback/jack.c +++ b/src/audio/playback/jack.c @@ -151,7 +151,8 @@ static void audio_play_jack_help(const char *client_name) free(available_devices); } -static void * audio_play_jack_init(const char *cfg) +static void * +audio_play_jack_init(const struct audio_playback_opts *opts) { const char **ports; jack_status_t status; @@ -173,7 +174,7 @@ static void * audio_play_jack_init(const char *cfg) } char dup[STR_LEN]; - snprintf_ch(dup, "%s", cfg); + snprintf_ch(dup, "%s", opts->cfg); char *tmp = dup, *item, *save_ptr; while ((item = strtok_r(tmp, ":", &save_ptr)) != NULL) { if (strcmp(item, "help") == 0) { @@ -193,7 +194,7 @@ static void * audio_play_jack_init(const char *cfg) } else if (strstr(item, "name=") == item) { strcpy(client_name, item + strlen("name=")); } else { // the rest is the device name - source_name = cfg + (item - dup); + source_name = opts->cfg + (item - dup); break; } tmp = NULL; diff --git a/src/audio/playback/mixer.cpp b/src/audio/playback/mixer.cpp index 074e47556..dcb3a1aee 100644 --- a/src/audio/playback/mixer.cpp +++ b/src/audio/playback/mixer.cpp @@ -414,14 +414,15 @@ static void audio_play_mixer_probe(struct device_info **available_devices, int * *count = 0; } -static void * audio_play_mixer_init(const char *cfg) +static void * +audio_play_mixer_init(const struct audio_playback_opts *opts) { - if (strcmp(cfg, "help") == 0) { + if (strcmp(opts->cfg, "help") == 0) { audio_play_mixer_help(); return INIT_NOERR; } try { - return new state_audio_mixer{cfg}; + return new state_audio_mixer{opts->cfg}; } catch (...) { return nullptr; } diff --git a/src/audio/playback/none.c b/src/audio/playback/none.c index 802d418ad..608de6340 100644 --- a/src/audio/playback/none.c +++ b/src/audio/playback/none.c @@ -35,18 +35,16 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" -#endif +#include // for assert +#include // for bool, false, true +#include // for uint32_t +#include // for free, malloc #include "audio/audio_playback.h" #include "audio/types.h" #include "debug.h" #include "lib_common.h" -#include -#include +struct device_info; #define AUDIO_PLAYBACK_NONE_MAGIC 0x3bcf376au @@ -62,13 +60,11 @@ static void audio_play_none_probe(struct device_info **available_devices, int *c *count = 0; } -static void * audio_play_none_init(const char *cfg) +static void * +audio_play_none_init(const struct audio_playback_opts *opts) { - UNUSED(cfg); - struct state_audio_playback_none *s; - - s = (struct state_audio_playback_none *) - malloc(sizeof(struct state_audio_playback_none)); + (void) opts; + struct state_audio_playback_none *s = malloc(sizeof(*s)); assert(s != NULL); s->magic = AUDIO_PLAYBACK_NONE_MAGIC; diff --git a/src/audio/playback/pipewire.cpp b/src/audio/playback/pipewire.cpp index 94bad947c..71467138b 100644 --- a/src/audio/playback/pipewire.cpp +++ b/src/audio/playback/pipewire.cpp @@ -118,10 +118,10 @@ static void on_process(void *userdata) noexcept{ } } -static void * audio_play_pw_init(const char *cfg){ +static void * audio_play_pw_init(const struct audio_playback_opts *opts){ auto s = std::make_unique(); - std::string_view cfg_sv(cfg); + std::string_view cfg_sv(opts->cfg); while(!cfg_sv.empty()){ auto tok = tokenize(cfg_sv, ':', '"'); auto key = tokenize(tok, '='); diff --git a/src/audio/playback/portaudio.c b/src/audio/playback/portaudio.c index bbe52bb6f..bdc1d8c71 100644 --- a/src/audio/playback/portaudio.c +++ b/src/audio/playback/portaudio.c @@ -167,18 +167,19 @@ static void audio_play_portaudio_help(void) { portaudio_print_help(PORTAUDIO_OUT); } -static void * audio_play_portaudio_init(const char *cfg) -{ +static void * +audio_play_portaudio_init(const struct audio_playback_opts *opts) +{ int output_device_idx = -1; char output_device_name[STR_LEN] = ""; portaudio_print_version(); - if (strcmp(cfg, "help") == 0) { + if (strcmp(opts->cfg, "help") == 0) { audio_play_portaudio_help(); return INIT_NOERR; } - if (!parse_fmt(cfg, &output_device_idx, output_device_name)) { + if (!parse_fmt(opts->cfg, &output_device_idx, output_device_name)) { return NULL; } diff --git a/src/audio/playback/sdi.c b/src/audio/playback/sdi.c index 0f3b4cdbc..cfc93bf59 100644 --- a/src/audio/playback/sdi.c +++ b/src/audio/playback/sdi.c @@ -35,22 +35,20 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#include "config_unix.h" -#include "config_win32.h" -#endif +#include "audio/playback/sdi.h" + +#include // for printf, snprintf +#include // for free, calloc, malloc +#include // for strcmp, strncpy, memcpy -#include "audio/audio.h" +#include "audio/types.h" // for audio_desc, audio_frame (ptr only) #include "audio/audio_playback.h" -#include "audio/playback/sdi.h" #include "debug.h" +#include "host.h" // for INIT_NOERR #include "lib_common.h" +#include "types.h" // for device_info #include "video_display.h" -#include -#include - struct state_sdi_playback { void *udata; void (*put_callback)(void *, const struct audio_frame *); @@ -98,9 +96,10 @@ static void audio_play_sdi_help(const char *driver_name) } } -static void * audio_play_sdi_init(const char *cfg) +static void * +audio_play_sdi_init(const struct audio_playback_opts *opts) { - if (strcmp(cfg, "help") == 0) { + if (strcmp(opts->cfg, "help") == 0) { printf("Available embedded devices:\n"); audio_play_sdi_help("embedded"); audio_play_sdi_help("AESEBU"); diff --git a/src/audio/playback/wasapi.cpp b/src/audio/playback/wasapi.cpp index 8b61f3400..05b3bc52a 100644 --- a/src/audio/playback/wasapi.cpp +++ b/src/audio/playback/wasapi.cpp @@ -204,19 +204,21 @@ static void audio_play_wasapi_help() { com_uninitialize(&com_initialized); } -static void * audio_play_wasapi_init(const char *cfg) +static void * +audio_play_wasapi_init(const struct audio_playback_opts *opts) { + if (strcmp(opts->cfg, "help") == 0) { + audio_play_wasapi_help(); + return INIT_NOERR; + } + wchar_t deviceID[1024] = L""; int index = -1; - if (strlen(cfg) > 0) { - if (strcmp(cfg, "help") == 0) { - audio_play_wasapi_help(); - return INIT_NOERR; - } - if (isdigit(cfg[0])) { - index = atoi(cfg); + if (strlen(opts->cfg) > 0) { + if (isdigit(opts->cfg[0])) { + index = atoi(opts->cfg); } else { - mbtowc(deviceID, cfg, (sizeof deviceID / 2) - 1); + mbtowc(deviceID, opts->cfg, (sizeof deviceID / 2) - 1); } } auto s = new state_aplay_wasapi();