diff options
author | horstderheld | 2021-07-14 15:05:05 +0200 |
---|---|---|
committer | horstderheld | 2021-07-14 15:05:05 +0200 |
commit | e2bab472c039a17f9782273391ebcd3b66e1eab8 (patch) | |
tree | 5eac1eaf0920a2b794669d8095dd5cea0c7503f2 | |
parent | c3fd7e8c90b3a7226af99715ce177102816c63c3 (diff) | |
download | aur-e2bab472c039a17f9782273391ebcd3b66e1eab8.tar.gz |
add media control by t-8ch
-rw-r--r-- | .SRCINFO | 7 | ||||
-rw-r--r-- | 01-Add-PipeWire-audio-backend-by-Oschowa.patch | 354 | ||||
-rw-r--r-- | 02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch | 209 | ||||
-rw-r--r-- | PKGBUILD | 14 |
4 files changed, 577 insertions, 7 deletions
@@ -1,7 +1,7 @@ pkgbase = mpv-pipewire pkgdesc = a free, open source, and cross-platform media player including an experimental PipeWire audio backend pkgver = 0.33.1 - pkgrel = 4 + pkgrel = 5 url = https://mpv.io/ arch = x86_64 license = GPL3 @@ -83,10 +83,11 @@ pkgbase = mpv-pipewire conflicts = mpv options = !emptydirs source = git+https://github.com/mpv-player/mpv.git#tag=4c9d3669a0f672e6754ac456acd324db570964d3?signed - source = pipewire.patch::https://github.com/Oschowa/mpv/commit/fddb143282fa74425a8a6f29c9566e51777759d0.patch + source = 01-Add-PipeWire-audio-backend-by-Oschowa.patch + source = 02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch validpgpkeys = 145077D82501AA20152CACCE8D769208D5E31419 sha256sums = SKIP sha256sums = d72a5863bceb5ac542c656ff85a9cb23d27d30c1609022e1b1735744f2777aaf + sha256sums = 1b1e69f06225b1f6c9a6ffdc7d3acccfcee3d25c350e4d1a0ab66f5dcb0d3bf3 pkgname = mpv-pipewire - diff --git a/01-Add-PipeWire-audio-backend-by-Oschowa.patch b/01-Add-PipeWire-audio-backend-by-Oschowa.patch new file mode 100644 index 000000000000..3b4d1ea005cb --- /dev/null +++ b/01-Add-PipeWire-audio-backend-by-Oschowa.patch @@ -0,0 +1,354 @@ +From fddb143282fa74425a8a6f29c9566e51777759d0 Mon Sep 17 00:00:00 2001 +From: Oschowa <oschowa@web.de> +Date: Tue, 3 Nov 2020 11:46:45 +0100 +Subject: [PATCH] Add PipeWire audio backend + +based on this original pull request +https://github.com/mpv-player/mpv/pull/7902 by andreaskem +--- + audio/out/ao.c | 4 + + audio/out/ao_pipewire.c | 284 ++++++++++++++++++++++++++++++++++++++++ + wscript | 4 + + wscript_build.py | 1 + + 4 files changed, 293 insertions(+) + create mode 100644 audio/out/ao_pipewire.c + +diff --git a/audio/out/ao.c b/audio/out/ao.c +index 52a38b63be2..74b290c9d9a 100644 +--- a/audio/out/ao.c ++++ b/audio/out/ao.c +@@ -40,6 +40,7 @@ extern const struct ao_driver audio_out_audiounit; + extern const struct ao_driver audio_out_coreaudio; + extern const struct ao_driver audio_out_coreaudio_exclusive; + extern const struct ao_driver audio_out_rsound; ++extern const struct ao_driver audio_out_pipewire; + extern const struct ao_driver audio_out_pulse; + extern const struct ao_driver audio_out_jack; + extern const struct ao_driver audio_out_openal; +@@ -62,6 +63,9 @@ static const struct ao_driver * const audio_out_drivers[] = { + #if HAVE_COREAUDIO + &audio_out_coreaudio, + #endif ++#if HAVE_PIPEWIRE ++ &audio_out_pipewire, ++#endif + #if HAVE_PULSE + &audio_out_pulse, + #endif +diff --git a/audio/out/ao_pipewire.c b/audio/out/ao_pipewire.c +new file mode 100644 +index 00000000000..79965cdc68b +--- /dev/null ++++ b/audio/out/ao_pipewire.c +@@ -0,0 +1,284 @@ ++ ++#include <pipewire/pipewire.h> ++#include <spa/param/audio/format-utils.h> ++ ++#include "common/msg.h" ++#include "options/m_config.h" ++#include "options/m_option.h" ++#include "ao.h" ++#include "audio/format.h" ++#include "config.h" ++#include "internal.h" ++#include "osdep/timer.h" ++ ++struct ao_pipewire_opts { ++ int buffer_samples; ++}; ++ ++#define OPT_BASE_STRUCT struct ao_pipewire_opts ++static const struct m_sub_options ao_pipewire_conf = { ++ .opts = (const struct m_option[]) { ++ {"pipewire-buffer-samples", OPT_INT(buffer_samples)}, ++ {0} ++ }, ++ .defaults = &(const struct ao_pipewire_opts) { ++ .buffer_samples = 2048, ++ }, ++ .size = sizeof(struct ao_pipewire_opts), ++}; ++ ++struct priv { ++ struct pw_thread_loop *loop; ++ struct pw_stream *stream; ++ ++ struct ao_pipewire_opts *opts; ++}; ++ ++static enum spa_audio_format af_fmt_to_pw(enum af_format format) ++{ ++ switch (format) { ++ case AF_FORMAT_U8: return SPA_AUDIO_FORMAT_U8; ++ case AF_FORMAT_S16: return SPA_AUDIO_FORMAT_S16; ++ case AF_FORMAT_S32: return SPA_AUDIO_FORMAT_S32; ++ case AF_FORMAT_FLOAT: return SPA_AUDIO_FORMAT_F32; ++ case AF_FORMAT_DOUBLE: return SPA_AUDIO_FORMAT_F64; ++ case AF_FORMAT_U8P: return SPA_AUDIO_FORMAT_U8P; ++ case AF_FORMAT_S16P: return SPA_AUDIO_FORMAT_S16P; ++ case AF_FORMAT_S32P: return SPA_AUDIO_FORMAT_S32P; ++ case AF_FORMAT_FLOATP: return SPA_AUDIO_FORMAT_F32P; ++ case AF_FORMAT_DOUBLEP: return SPA_AUDIO_FORMAT_F64P; ++ default: return SPA_AUDIO_FORMAT_UNKNOWN; ++ } ++} ++ ++static const enum spa_audio_channel mp_speaker_id_to_spa[] = { ++ [MP_SPEAKER_ID_FL] = SPA_AUDIO_CHANNEL_FL, ++ [MP_SPEAKER_ID_FR] = SPA_AUDIO_CHANNEL_FR, ++ [MP_SPEAKER_ID_FC] = SPA_AUDIO_CHANNEL_FC, ++ [MP_SPEAKER_ID_LFE] = SPA_AUDIO_CHANNEL_LFE, ++ [MP_SPEAKER_ID_BL] = SPA_AUDIO_CHANNEL_RL, ++ [MP_SPEAKER_ID_BR] = SPA_AUDIO_CHANNEL_RR, ++ [MP_SPEAKER_ID_FLC] = SPA_AUDIO_CHANNEL_FLC, ++ [MP_SPEAKER_ID_FRC] = SPA_AUDIO_CHANNEL_FRC, ++ [MP_SPEAKER_ID_BC] = SPA_AUDIO_CHANNEL_RC, ++ [MP_SPEAKER_ID_SL] = SPA_AUDIO_CHANNEL_SL, ++ [MP_SPEAKER_ID_SR] = SPA_AUDIO_CHANNEL_SR, ++ [MP_SPEAKER_ID_TC] = SPA_AUDIO_CHANNEL_TC, ++ [MP_SPEAKER_ID_TFL] = SPA_AUDIO_CHANNEL_TFL, ++ [MP_SPEAKER_ID_TFC] = SPA_AUDIO_CHANNEL_TFC, ++ [MP_SPEAKER_ID_TFR] = SPA_AUDIO_CHANNEL_TFR, ++ [MP_SPEAKER_ID_TBL] = SPA_AUDIO_CHANNEL_TRL, ++ [MP_SPEAKER_ID_TBC] = SPA_AUDIO_CHANNEL_TRC, ++ [MP_SPEAKER_ID_TBR] = SPA_AUDIO_CHANNEL_TRR, ++ [MP_SPEAKER_ID_DL] = SPA_AUDIO_CHANNEL_FL, ++ [MP_SPEAKER_ID_DR] = SPA_AUDIO_CHANNEL_FR, ++ [MP_SPEAKER_ID_WL] = SPA_AUDIO_CHANNEL_FL, ++ [MP_SPEAKER_ID_WR] = SPA_AUDIO_CHANNEL_FR, ++ [MP_SPEAKER_ID_SDL] = SPA_AUDIO_CHANNEL_SL, ++ [MP_SPEAKER_ID_SDR] = SPA_AUDIO_CHANNEL_SL, ++ [MP_SPEAKER_ID_LFE2] = SPA_AUDIO_CHANNEL_LFE2, ++ [MP_SPEAKER_ID_NA] = SPA_AUDIO_CHANNEL_NA, ++}; ++ ++static void on_process(void *userdata) ++{ ++ struct ao *ao = userdata; ++ struct priv *p = ao->priv; ++ struct pw_time time; ++ struct pw_buffer *b; ++ void *data[MP_NUM_CHANNELS]; ++ ++ if ((b = pw_stream_dequeue_buffer(p->stream)) == NULL) { ++ pw_log_warn("out of buffers: %m"); ++ return; ++ } ++ ++ struct spa_buffer *buf = b->buffer; ++ ++ int bytes_per_channel = buf->datas[0].maxsize / ao->channels.num; ++ int nframes = bytes_per_channel / ao->sstride; ++ ++ for (int i = 0; i < buf->n_datas; i++) { ++ data[i] = buf->datas[i].data; ++ buf->datas[i].chunk->size = bytes_per_channel; ++ buf->datas[i].chunk->offset = 0; ++ } ++ ++ pw_stream_get_time(p->stream, &time); ++ if (time.rate.denom == 0) ++ time.rate.denom = ao->samplerate; ++ ++ int64_t end_time = mp_time_us(); ++ /* time.queued is always going to be 0, so we don't need to care */ ++ end_time += (nframes + time.delay) * SPA_USEC_PER_SEC / time.rate.denom; ++ ++ ao_read_data(ao, data, nframes, end_time); ++ ++ pw_stream_queue_buffer(p->stream, b); ++} ++ ++static void on_param_changed(void *userdata, uint32_t id, const struct spa_pod *param) ++{ ++ struct ao *ao = userdata; ++ struct priv *p = ao->priv; ++ const struct spa_pod *params[1]; ++ uint8_t buffer[1024]; ++ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); ++ ++ if (param == NULL || id != SPA_PARAM_Format) ++ return; ++ ++ int buffer_size = ao->device_buffer * af_fmt_to_bytes(ao->format) * ao->channels.num; ++ ++ params[0] = spa_pod_builder_add_object(&b, ++ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, ++ SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(ao->num_planes), ++ SPA_PARAM_BUFFERS_size, SPA_POD_Int(buffer_size), ++ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(ao->sstride)); ++ ++ pw_stream_update_params(p->stream, params, 1); ++} ++ ++static void on_state_changed(void *userdata, enum pw_stream_state old, enum pw_stream_state state, const char *error) ++{ ++ struct ao *ao = userdata; ++ MP_DBG(ao, "Stream state changed: old_state=%d state=%d error=%s\n", old, state, error); ++ ++ if (state == PW_STREAM_STATE_ERROR) { ++ MP_WARN(ao, "Stream in error state, trying to reload...\n"); ++ ao_request_reload(ao); ++ } ++} ++ ++static const struct pw_stream_events stream_events = { ++ .version = PW_VERSION_STREAM_EVENTS, ++ .param_changed = on_param_changed, ++ .process = on_process, ++ .state_changed = on_state_changed, ++}; ++ ++static void uninit(struct ao *ao) ++{ ++ struct priv *p = ao->priv; ++ if (p->loop) ++ pw_thread_loop_stop(p->loop); ++ if (p->stream) ++ pw_stream_destroy(p->stream); ++ p->stream = NULL; ++ if (p->loop) ++ pw_thread_loop_destroy(p->loop); ++ p->loop = NULL; ++ pw_deinit(); ++} ++ ++static int init(struct ao *ao) ++{ ++ struct priv *p = ao->priv; ++ uint8_t buffer[1024]; ++ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); ++ const struct spa_pod *params[1]; ++ char latency_str[64]; ++ ++ p->opts = mp_get_config_group(ao, ao->global, &ao_pipewire_conf); ++ ++ enum spa_audio_format spa_format = af_fmt_to_pw(ao->format); ++ if (spa_format == SPA_AUDIO_FORMAT_UNKNOWN) { ++ ao->format = AF_FORMAT_FLOATP; ++ spa_format = SPA_AUDIO_FORMAT_F32P; ++ } ++ ++ struct spa_audio_info_raw audio_info = { ++ .format = spa_format, ++ .rate = ao->samplerate, ++ .channels = ao->channels.num, ++ }; ++ ++ for (int i = 0; i < ao->channels.num; i++) ++ audio_info.position[i] = mp_speaker_id_to_spa[ao->channels.speaker[i]]; ++ ++ params[0] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &audio_info); ++ ++ if (af_fmt_is_planar(ao->format)) { ++ ao->num_planes = ao->channels.num; ++ ao->sstride = af_fmt_to_bytes(ao->format); ++ } else { ++ ao->num_planes = 1; ++ ao->sstride = ao->channels.num * af_fmt_to_bytes(ao->format); ++ } ++ ++ ao->device_buffer = p->opts->buffer_samples; ++ snprintf(latency_str, sizeof(latency_str), "%d/%d", ao->device_buffer, ao->samplerate); ++ ++ pw_init(NULL, NULL); ++ ++ p->loop = pw_thread_loop_new("ao-pipewire", NULL); ++ if (p->loop == NULL) ++ goto error; ++ ++ p->stream = pw_stream_new_simple( ++ pw_thread_loop_get_loop(p->loop), ++ "audio-src", ++ pw_properties_new( ++ PW_KEY_MEDIA_TYPE, "Audio", ++ PW_KEY_MEDIA_CATEGORY, "Playback", ++ PW_KEY_MEDIA_ROLE, "Music", ++ PW_KEY_NODE_NAME, "mpv", ++ PW_KEY_NODE_LATENCY, latency_str, ++ NULL), ++ &stream_events, ++ ao); ++ if (p->stream == NULL) ++ goto error; ++ ++ if (pw_stream_connect(p->stream, ++ PW_DIRECTION_OUTPUT, ++ PW_ID_ANY, ++ PW_STREAM_FLAG_AUTOCONNECT | ++ PW_STREAM_FLAG_MAP_BUFFERS | ++ PW_STREAM_FLAG_RT_PROCESS, ++ params, 1) < 0) ++ goto error; ++ ++ if (pw_thread_loop_start(p->loop) < 0) ++ goto error; ++ ++ return 0; ++ ++error: ++ uninit(ao); ++ return -1; ++} ++ ++static void reset(struct ao *ao) ++{ ++ struct priv *p = ao->priv; ++ pw_thread_loop_lock(p->loop); ++ pw_stream_set_active(p->stream, false); ++ pw_thread_loop_unlock(p->loop); ++} ++ ++static void start(struct ao *ao) ++{ ++ struct priv *p = ao->priv; ++ pw_thread_loop_lock(p->loop); ++ pw_stream_set_active(p->stream, true); ++ pw_thread_loop_unlock(p->loop); ++} ++ ++const struct ao_driver audio_out_pipewire = { ++ .description = "PipeWire audio output", ++ .name = "pipewire", ++ ++ .init = init, ++ .uninit = uninit, ++ .reset = reset, ++ .start = start, ++ ++ .priv_size = sizeof(struct priv), ++ .priv_defaults = &(const struct priv) ++ { ++ .loop = NULL, ++ .stream = NULL, ++ }, ++ .global_opts = &ao_pipewire_conf, ++}; +diff --git a/wscript b/wscript +index 86231b79b1b..61e07281053 100644 +--- a/wscript ++++ b/wscript +@@ -421,6 +421,10 @@ audio_output_features = [ + 'desc': 'SDL2 audio output', + 'deps': 'sdl2', + 'func': check_true, ++ }, { ++ 'name': '--pipewire', ++ 'desc': 'PipeWire audio output', ++ 'func': check_pkg_config('libpipewire-0.3', '>= 0.3.0') + }, { + 'name': '--pulse', + 'desc': 'PulseAudio audio output', +diff --git a/wscript_build.py b/wscript_build.py +index 14c254e1ec9..4613fabe70f 100644 +--- a/wscript_build.py ++++ b/wscript_build.py +@@ -245,6 +245,7 @@ def swift(task): + ( "audio/out/ao_openal.c", "openal" ), + ( "audio/out/ao_opensles.c", "opensles" ), + ( "audio/out/ao_pcm.c" ), ++ ( "audio/out/ao_pipewire.c", "pipewire" ), + ( "audio/out/ao_pulse.c", "pulse" ), + ( "audio/out/ao_sdl.c", "sdl2-audio" ), + ( "audio/out/ao_wasapi.c", "wasapi" ), diff --git a/02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch b/02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch new file mode 100644 index 000000000000..fd7313e863ba --- /dev/null +++ b/02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch @@ -0,0 +1,209 @@ +From 464391e216400874a46679b6f978e0c36a040e5c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <thomas@t-8ch.de> +Date: Tue, 8 Jun 2021 00:24:00 +0200 +Subject: [PATCH 1/3] ao_pipewire: whitespace fixes + +--- + audio/out/ao_pipewire.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/audio/out/ao_pipewire.c b/audio/out/ao_pipewire.c +index 79965cdc68b..b0102bee8ea 100644 +--- a/audio/out/ao_pipewire.c ++++ b/audio/out/ao_pipewire.c +@@ -121,9 +121,9 @@ static void on_param_changed(void *userdata, uint32_t id, const struct spa_pod * + { + struct ao *ao = userdata; + struct priv *p = ao->priv; +- const struct spa_pod *params[1]; +- uint8_t buffer[1024]; +- struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); ++ const struct spa_pod *params[1]; ++ uint8_t buffer[1024]; ++ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + + if (param == NULL || id != SPA_PARAM_Format) + return; + +From af10f39b030a0d5c985c8f7d04bf7f7ea2904d5e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <thomas@t-8ch.de> +Date: Tue, 8 Jun 2021 00:24:06 +0200 +Subject: [PATCH 2/3] ao_pipewire: add more application properties + +--- + audio/out/ao_pipewire.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/audio/out/ao_pipewire.c b/audio/out/ao_pipewire.c +index b0102bee8ea..9f2a66ad845 100644 +--- a/audio/out/ao_pipewire.c ++++ b/audio/out/ao_pipewire.c +@@ -8,6 +8,7 @@ + #include "ao.h" + #include "audio/format.h" + #include "config.h" ++#include "generated/version.h" + #include "internal.h" + #include "osdep/timer.h" + +@@ -222,7 +223,10 @@ static int init(struct ao *ao) + PW_KEY_MEDIA_TYPE, "Audio", + PW_KEY_MEDIA_CATEGORY, "Playback", + PW_KEY_MEDIA_ROLE, "Music", +- PW_KEY_NODE_NAME, "mpv", ++ PW_KEY_NODE_NAME, ao->client_name, ++ PW_KEY_APP_NAME, ao->client_name, ++ PW_KEY_APP_ID, ao->client_name, ++ PW_KEY_APP_ICON_NAME, ao->client_name, + PW_KEY_NODE_LATENCY, latency_str, + NULL), + &stream_events, + +From 3df9d344f0c05df90b421bbde3616be8f84d9f35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= <thomas@t-8ch.de> +Date: Tue, 8 Jun 2021 00:24:11 +0200 +Subject: [PATCH 3/3] ap_pipewire: implement audio controls + +--- + audio/out/ao_pipewire.c | 95 +++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 95 insertions(+) + +diff --git a/audio/out/ao_pipewire.c b/audio/out/ao_pipewire.c +index 9f2a66ad845..a5c4322eebe 100644 +--- a/audio/out/ao_pipewire.c ++++ b/audio/out/ao_pipewire.c +@@ -1,6 +1,8 @@ + + #include <pipewire/pipewire.h> + #include <spa/param/audio/format-utils.h> ++#include <spa/param/props.h> ++#include <math.h> + + #include "common/msg.h" + #include "options/m_config.h" +@@ -33,6 +35,8 @@ struct priv { + struct pw_stream *stream; + + struct ao_pipewire_opts *opts; ++ bool muted; ++ float volume[2]; + }; + + static enum spa_audio_format af_fmt_to_pw(enum af_format format) +@@ -151,11 +155,44 @@ static void on_state_changed(void *userdata, enum pw_stream_state old, enum pw_s + } + } + ++static float spa_volume_to_mp_volume(float vol) ++{ ++ return cbrt(vol) * 100; ++} ++ ++static float mp_volume_to_spa_volume(float vol) ++{ ++ vol /= 100; ++ return vol * vol * vol; ++} ++ ++static void on_control_info(void *userdata, uint32_t id, ++ const struct pw_stream_control *control) ++{ ++ struct ao *ao = userdata; ++ struct priv *p = ao->priv; ++ ++ switch (id) { ++ case SPA_PROP_mute: ++ if (control->n_values == 1) ++ p->muted = control->values[0] >= 0.5; ++ break; ++ case SPA_PROP_channelVolumes: ++ if (control->n_values == 2) { ++ p->volume[0] = control->values[0]; ++ p->volume[1] = control->values[1]; ++ } ++ break; ++ } ++} ++ ++ + static const struct pw_stream_events stream_events = { + .version = PW_VERSION_STREAM_EVENTS, + .param_changed = on_param_changed, + .process = on_process, + .state_changed = on_state_changed, ++ .control_info = on_control_info, + }; + + static void uninit(struct ao *ao) +@@ -269,6 +306,62 @@ static void start(struct ao *ao) + pw_thread_loop_unlock(p->loop); + } + ++#define CONTROL_RET(r) (!r ? CONTROL_OK : CONTROL_ERROR) ++ ++static int control(struct ao *ao, enum aocontrol cmd, void *arg) ++{ ++ struct priv *p = ao->priv; ++ ++ switch (cmd) { ++ case AOCONTROL_GET_VOLUME: { ++ struct ao_control_vol *vol = arg; ++ vol->left = spa_volume_to_mp_volume(p->volume[0]); ++ vol->right = spa_volume_to_mp_volume(p->volume[1]); ++ return CONTROL_OK; ++ } ++ case AOCONTROL_GET_MUTE: { ++ bool *muted = arg; ++ *muted = p->muted; ++ return CONTROL_OK; ++ } ++ case AOCONTROL_SET_VOLUME: ++ case AOCONTROL_SET_MUTE: ++ case AOCONTROL_UPDATE_STREAM_TITLE: { ++ int ret; ++ ++ pw_thread_loop_lock(p->loop); ++ switch (cmd) { ++ case AOCONTROL_SET_VOLUME: { ++ struct ao_control_vol *vol = arg; ++ float left = mp_volume_to_spa_volume(vol->left), right = mp_volume_to_spa_volume(vol->right); ++ ret = CONTROL_RET(pw_stream_set_control(p->stream, SPA_PROP_channelVolumes, 2, &left, &right)); ++ break; ++ } ++ case AOCONTROL_SET_MUTE: { ++ bool *muted = arg; ++ float value = *muted ? 1.f : 0.f; ++ ret = CONTROL_RET(pw_stream_set_control(p->stream, SPA_PROP_mute, 1, &value)); ++ break; ++ } ++ case AOCONTROL_UPDATE_STREAM_TITLE: { ++ char *title = arg; ++ struct spa_dict_item items[1]; ++ items[0] = SPA_DICT_ITEM_INIT(PW_KEY_MEDIA_NAME, title); ++ ret = CONTROL_RET(pw_stream_update_properties(p->stream, &SPA_DICT_INIT(items, MP_ARRAY_SIZE(items)))); ++ break; ++ } ++ default: ++ ret = CONTROL_NA; ++ } ++ pw_thread_loop_unlock(p->loop); ++ return ret; ++ } ++ default: ++ return CONTROL_UNKNOWN; ++ } ++} ++ ++ + const struct ao_driver audio_out_pipewire = { + .description = "PipeWire audio output", + .name = "pipewire", +@@ -278,6 +371,8 @@ const struct ao_driver audio_out_pipewire = { + .reset = reset, + .start = start, + ++ .control = control, ++ + .priv_size = sizeof(struct priv), + .priv_defaults = &(const struct priv) + { @@ -7,7 +7,7 @@ _pkgname=mpv pkgname=${_pkgname}-pipewire _tag='4c9d3669a0f672e6754ac456acd324db570964d3' # git rev-parse v${pkgver} pkgver=0.33.1 -pkgrel=4 +pkgrel=5 pkgdesc='a free, open source, and cross-platform media player including an experimental PipeWire audio backend' arch=('x86_64') # We link against libraries that are licensed GPLv3 explicitly, so our @@ -33,9 +33,11 @@ conflicts=('mpv') options=('!emptydirs') validpgpkeys=('145077D82501AA20152CACCE8D769208D5E31419') # sfan5 <sfan5@live.de> source=("git+https://github.com/mpv-player/mpv.git#tag=${_tag}?signed" - "pipewire.patch::https://github.com/Oschowa/mpv/commit/fddb143282fa74425a8a6f29c9566e51777759d0.patch") + "01-Add-PipeWire-audio-backend-by-Oschowa.patch" + "02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch") sha256sums=('SKIP' - 'd72a5863bceb5ac542c656ff85a9cb23d27d30c1609022e1b1735744f2777aaf') + 'd72a5863bceb5ac542c656ff85a9cb23d27d30c1609022e1b1735744f2777aaf' + '1b1e69f06225b1f6c9a6ffdc7d3acccfcee3d25c350e4d1a0ab66f5dcb0d3bf3') prepare() { cd ${_pkgname} @@ -44,7 +46,11 @@ prepare() { git cherry-pick -n 7c4465cefb27d4e0d07535d368febdf77b579566 # patch mpv with the PipeWire audio backend - patch -Np1 -i ../pipewire.patch + #https://github.com/Oschowa/mpv/commit/fddb143282fa74425a8a6f29c9566e51777759d0 + patch -Np1 -i ../01-Add-PipeWire-audio-backend-by-Oschowa.patch + # add ao_pipewire fixes and media control + # https://github.com/Oschowa/mpv/pull/1 + patch -Np1 -i ../02-ao_pipewire-fixes-and-media-control-by-t-8ch.patch } build() { |