From 6e8b9dea2955da6a2e7f9c1d9e7bc91bf960dce6 Mon Sep 17 00:00:00 2001 From: NBonaparte Date: Tue, 26 Sep 2017 15:21:23 -0700 Subject: [PATCH] fix(pulseaudio): Move pulseaudio to separate module --- build.sh | 2 +- cmake/02-opts.cmake | 3 - doc/CMakeLists.txt | 2 +- include/modules/meta/factory.hpp | 9 +- include/modules/pulseaudio.hpp | 58 +++++++++++ include/modules/unsupported.hpp | 7 +- include/modules/volume.hpp | 13 --- src/CMakeLists.txt | 5 +- src/modules/pulseaudio.cpp | 161 +++++++++++++++++++++++++++++++ src/modules/volume.cpp | 64 +----------- 10 files changed, 236 insertions(+), 88 deletions(-) create mode 100644 include/modules/pulseaudio.hpp create mode 100644 src/modules/pulseaudio.cpp diff --git a/build.sh b/build.sh index a84530f8..3c8bae0a 100755 --- a/build.sh +++ b/build.sh @@ -42,7 +42,7 @@ function main [[ "${p^^}" != "Y" ]] && enable_i3="OFF" read -r -p "$(msg "Include support for \"internal/volume\" (requires alsalib) ---------- [Y/n]: ")" -n 1 p && echo [[ "${p^^}" != "Y" ]] && enable_alsa="OFF" - read -r -p "$(msg "Include support for \"internal/volume\" (requires libpulse) --------- [Y/n]: ")" -n 1 p && echo + read -r -p "$(msg "Include support for \"internal/pulseaudio\" (requires libpulse) ----- [Y/n]: ")" -n 1 p && echo [[ "${p^^}" != "Y" ]] && enable_pulseaudio="OFF" read -r -p "$(msg "Include support for \"internal/network\" (requires wireless_tools) -- [Y/n]: ")" -n 1 p && echo [[ "${p^^}" != "Y" ]] && enable_network="OFF" diff --git a/cmake/02-opts.cmake b/cmake/02-opts.cmake index 7ffdccbb..557e9a14 100644 --- a/cmake/02-opts.cmake +++ b/cmake/02-opts.cmake @@ -31,9 +31,6 @@ option(ENABLE_MPD "Enable mpd support" ON) option(ENABLE_NETWORK "Enable network support" ON) option(ENABLE_XKEYBOARD "Enable xkeyboard support" ON) option(ENABLE_PULSEAUDIO "Enable PulseAudio support" ON) -if(ENABLE_PULSEAUDIO) - set(ENABLE_ALSA OFF) -endif() option(WITH_XRANDR "xcb-randr support" ON) option(WITH_XRANDR_MONITORS "xcb-randr monitor support" ON) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index b14d452c..e265ca5a 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -16,7 +16,7 @@ queryfont(FONT_SIJI ${FONT_SIJI} FIELDS family pixelsize) # Strip disabled modules {{{ -if(NOT (ENABLE_ALSA OR ENABLE_PULSEAUDIO)) +if(NOT ENABLE_ALSA) string(REPLACE " volume" "" MODULES_RIGHT ${MODULES_RIGHT}) endif() if(NOT ENABLE_I3) diff --git a/include/modules/meta/factory.hpp b/include/modules/meta/factory.hpp index 8e510c58..bd94482e 100644 --- a/include/modules/meta/factory.hpp +++ b/include/modules/meta/factory.hpp @@ -31,16 +31,19 @@ #if ENABLE_NETWORK #include "modules/network.hpp" #endif -#if ENABLE_ALSA || ENABLE_PULSEAUDIO +#if ENABLE_ALSA #include "modules/volume.hpp" #endif +#if ENABLE_PULSEAUDIO +#include "modules/pulseaudio.hpp" +#endif #if ENABLE_CURL #include "modules/github.hpp" #endif #if ENABLE_XKEYBOARD #include "modules/xkeyboard.hpp" #endif -#if not(ENABLE_I3 && ENABLE_MPD && ENABLE_NETWORK && (ENABLE_ALSA || ENABLE_PULSEAUDIO) && ENABLE_CURL && ENABLE_XKEYBOARD) +#if not(ENABLE_I3 && ENABLE_MPD && ENABLE_NETWORK && ENABLE_ALSA && ENABLE_PULSEAUDIO && ENABLE_CURL && ENABLE_XKEYBOARD) #include "modules/unsupported.hpp" #endif @@ -74,6 +77,8 @@ namespace { return new mpd_module(bar, move(module_name)); } else if (name == "internal/volume") { return new volume_module(bar, move(module_name)); + } else if (name == "internal/pulseaudio") { + return new pulseaudio_module(bar, move(module_name)); } else if (name == "internal/network") { return new network_module(bar, move(module_name)); #if DEBUG diff --git a/include/modules/pulseaudio.hpp b/include/modules/pulseaudio.hpp new file mode 100644 index 00000000..a2598086 --- /dev/null +++ b/include/modules/pulseaudio.hpp @@ -0,0 +1,58 @@ +#pragma once + +#include "settings.hpp" +#include "modules/meta/event_module.hpp" +#include "modules/meta/input_handler.hpp" + +POLYBAR_NS + +// fwd +class pulseaudio; + +namespace modules { + using pulseaudio_t = shared_ptr; + + class pulseaudio_module : public event_module, public input_handler { + public: + explicit pulseaudio_module(const bar_settings&, string); + + void teardown(); + bool has_event(); + bool update(); + string get_format() const; + string get_output(); + bool build(builder* builder, const string& tag) const; + + protected: + bool input(string&& cmd); + + private: + static constexpr auto FORMAT_VOLUME = "format-volume"; + static constexpr auto FORMAT_MUTED = "format-muted"; + + static constexpr auto TAG_RAMP_VOLUME = ""; + static constexpr auto TAG_RAMP_HEADPHONES = ""; + static constexpr auto TAG_BAR_VOLUME = ""; + static constexpr auto TAG_LABEL_VOLUME = ""; + static constexpr auto TAG_LABEL_MUTED = ""; + + static constexpr auto EVENT_PREFIX = "vol"; + static constexpr auto EVENT_VOLUME_UP = "volup"; + static constexpr auto EVENT_VOLUME_DOWN = "voldown"; + static constexpr auto EVENT_TOGGLE_MUTE = "volmute"; + + progressbar_t m_bar_volume; + ramp_t m_ramp_volume; + ramp_t m_ramp_headphones; + label_t m_label_volume; + label_t m_label_muted; + + pulseaudio_t m_pulseaudio; + + atomic m_muted{false}; + atomic m_headphones{false}; + atomic m_volume{0}; + }; +} + +POLYBAR_NS_END diff --git a/include/modules/unsupported.hpp b/include/modules/unsupported.hpp index f9c2746e..39822900 100644 --- a/include/modules/unsupported.hpp +++ b/include/modules/unsupported.hpp @@ -1,5 +1,5 @@ #pragma once -#if ENABLE_I3 && ENABLE_MPD && ENABLE_NETWORK && (ENABLE_ALSA || ENABLE_PULSEAUDIO) && ENABLE_CURL && ENABLE_XKEYBOARD +#if ENABLE_I3 && ENABLE_MPD && ENABLE_NETWORK && ENABLE_ALSA && ENABLE_PULSEAUDIO && ENABLE_CURL && ENABLE_XKEYBOARD #error "Support has been enabled for all optional modules" #endif @@ -40,9 +40,12 @@ namespace modules { #if not ENABLE_NETWORK DEFINE_UNSUPPORTED_MODULE(network_module, "internal/network"); #endif -#if not (ENABLE_ALSA || ENABLE_PULSEAUDIO) +#if not ENABLE_ALSA DEFINE_UNSUPPORTED_MODULE(volume_module, "internal/volume"); #endif +#if not ENABLE_PULSEAUDIO + DEFINE_UNSUPPORTED_MODULE(pulseaudio_module, "internal/pulseaudio"); +#endif #if not ENABLE_CURL DEFINE_UNSUPPORTED_MODULE(github_module, "internal/github"); #endif diff --git a/include/modules/volume.hpp b/include/modules/volume.hpp index 008e6772..8c86665f 100644 --- a/include/modules/volume.hpp +++ b/include/modules/volume.hpp @@ -7,25 +7,17 @@ POLYBAR_NS // fwd -#if ENABLE_ALSA namespace alsa { class mixer; class control; } -#elif ENABLE_PULSEAUDIO -class pulseaudio; -#endif namespace modules { enum class mixer { NONE = 0, MASTER, SPEAKER, HEADPHONE }; enum class control { NONE = 0, HEADPHONE }; -#if ENABLE_ALSA using mixer_t = shared_ptr; using control_t = shared_ptr; -#elif ENABLE_PULSEAUDIO - using pulseaudio_t = shared_ptr; -#endif class volume_module : public event_module, public input_handler { public: @@ -62,15 +54,10 @@ namespace modules { label_t m_label_volume; label_t m_label_muted; -#if ENABLE_PULSEAUDIO - pulseaudio_t m_pulseaudio; -#elif ENABLE_ALSA map m_mixer; map m_ctrl; - int m_headphoneid{0}; bool m_mapped{false}; -#endif atomic m_muted{false}; atomic m_headphones{false}; atomic m_volume{0}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 36c892cf..f49aa88d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ file(GLOB_RECURSE files RELATIVE ${CMAKE_CURRENT_LIST_DIR} *.c[p]*) list(REMOVE_ITEM files ipc.cpp) if(NOT ENABLE_ALSA) + list(REMOVE_ITEM files modules/volume.cpp) list(REMOVE_ITEM files adapters/alsa/control.cpp) list(REMOVE_ITEM files adapters/alsa/mixer.cpp) endif() @@ -28,11 +29,9 @@ if(NOT ENABLE_I3) list(REMOVE_ITEM files utils/i3.cpp) endif() if(NOT ENABLE_PULSEAUDIO) + list(REMOVE_ITEM files modules/pulseaudio.cpp) list(REMOVE_ITEM files adapters/pulseaudio.cpp) endif() -if(NOT (ENABLE_ALSA OR ENABLE_PULSEAUDIO)) - list(REMOVE_ITEM files modules/volume.cpp) -endif() if(NOT WITH_XRANDR) list(REMOVE_ITEM files x11/extensions/randr.cpp) endif() diff --git a/src/modules/pulseaudio.cpp b/src/modules/pulseaudio.cpp new file mode 100644 index 00000000..037567b9 --- /dev/null +++ b/src/modules/pulseaudio.cpp @@ -0,0 +1,161 @@ +#include "modules/pulseaudio.hpp" +#include "adapters/pulseaudio.hpp" +#include "drawtypes/label.hpp" +#include "drawtypes/progressbar.hpp" +#include "drawtypes/ramp.hpp" +#include "utils/math.hpp" + +#include "modules/meta/base.inl" + +#include "settings.hpp" + +POLYBAR_NS + +namespace modules { + template class module; + + pulseaudio_module::pulseaudio_module(const bar_settings& bar, string name_) : event_module(bar, move(name_)) { + // Load configuration values + auto sink_name = m_conf.get(name(), "sink", ""s); + try { + m_pulseaudio = factory_util::unique(move(sink_name)); + } catch (const pulseaudio_error& err) { + throw module_error(err.what()); + } + + // Add formats and elements + m_formatter->add(FORMAT_VOLUME, TAG_LABEL_VOLUME, {TAG_RAMP_VOLUME, TAG_LABEL_VOLUME, TAG_BAR_VOLUME}); + m_formatter->add(FORMAT_MUTED, TAG_LABEL_MUTED, {TAG_RAMP_VOLUME, TAG_LABEL_MUTED, TAG_BAR_VOLUME}); + + if (m_formatter->has(TAG_BAR_VOLUME)) { + m_bar_volume = load_progressbar(m_bar, m_conf, name(), TAG_BAR_VOLUME); + } + if (m_formatter->has(TAG_LABEL_VOLUME, FORMAT_VOLUME)) { + m_label_volume = load_optional_label(m_conf, name(), TAG_LABEL_VOLUME, "%percentage%%"); + } + if (m_formatter->has(TAG_LABEL_MUTED, FORMAT_MUTED)) { + m_label_muted = load_optional_label(m_conf, name(), TAG_LABEL_MUTED, "%percentage%%"); + } + if (m_formatter->has(TAG_RAMP_VOLUME)) { + m_ramp_volume = load_ramp(m_conf, name(), TAG_RAMP_VOLUME); + m_ramp_headphones = load_ramp(m_conf, name(), TAG_RAMP_HEADPHONES, false); + } + } + + void pulseaudio_module::teardown() { + m_pulseaudio.reset(); + } + + bool pulseaudio_module::has_event() { + // Poll for mixer and control events + try { + if (m_pulseaudio->wait(25)) + return true; + } catch (const pulseaudio_error& e) { + m_log.err("%s: %s", name(), e.what()); + } + return false; + } + + bool pulseaudio_module::update() { + // Consume pending events + m_pulseaudio->process_events(); + + // Get volume, mute and headphone state + m_volume = 100; + m_muted = false; + m_headphones = false; + + try { + if (m_pulseaudio) { + m_volume = m_volume * m_pulseaudio->get_volume() / 100.0f; + m_muted = m_muted || m_pulseaudio->is_muted(); + } + } catch (const pulseaudio_error& err) { + m_log.err("%s: Failed to query pulseaudio sink (%s)", name(), err.what()); + } + + // Replace label tokens + if (m_label_volume) { + m_label_volume->reset_tokens(); + m_label_volume->replace_token("%percentage%", to_string(m_volume)); + } + + if (m_label_muted) { + m_label_muted->reset_tokens(); + m_label_muted->replace_token("%percentage%", to_string(m_volume)); + } + + return true; + } + + string pulseaudio_module::get_format() const { + return m_muted ? FORMAT_MUTED : FORMAT_VOLUME; + } + + string pulseaudio_module::get_output() { + // Get the module output early so that + // the format prefix/suffix also gets wrapper + // with the cmd handlers + string output{module::get_output()}; + + if (m_handle_events) { + m_builder->cmd(mousebtn::LEFT, EVENT_TOGGLE_MUTE); + m_builder->cmd(mousebtn::SCROLL_UP, EVENT_VOLUME_UP); + m_builder->cmd(mousebtn::SCROLL_DOWN, EVENT_VOLUME_DOWN); + } + + m_builder->append(output); + + return m_builder->flush(); + } + + bool pulseaudio_module::build(builder* builder, const string& tag) const { + if (tag == TAG_BAR_VOLUME) { + builder->node(m_bar_volume->output(m_volume)); + } else if (tag == TAG_RAMP_VOLUME && (!m_headphones || !*m_ramp_headphones)) { + builder->node(m_ramp_volume->get_by_percentage(m_volume)); + } else if (tag == TAG_RAMP_VOLUME && m_headphones && *m_ramp_headphones) { + builder->node(m_ramp_headphones->get_by_percentage(m_volume)); + } else if (tag == TAG_LABEL_VOLUME) { + builder->node(m_label_volume); + } else if (tag == TAG_LABEL_MUTED) { + builder->node(m_label_muted); + } else { + return false; + } + return true; + } + + bool pulseaudio_module::input(string&& cmd) { + if (!m_handle_events) { + return false; + } else if (cmd.compare(0, 3, EVENT_PREFIX) != 0) { + return false; + } + + try { + if (m_pulseaudio && !m_pulseaudio->get_name().empty()) { + if (cmd.compare(0, strlen(EVENT_TOGGLE_MUTE), EVENT_TOGGLE_MUTE) == 0) { + m_pulseaudio->toggle_mute(); + } else if (cmd.compare(0, strlen(EVENT_VOLUME_UP), EVENT_VOLUME_UP) == 0) { + // cap above 100 (~150)? + m_pulseaudio->inc_volume(5); + } else if (cmd.compare(0, strlen(EVENT_VOLUME_DOWN), EVENT_VOLUME_DOWN) == 0) { + m_pulseaudio->inc_volume(-5); + } else { + return false; + } + if (m_pulseaudio->wait(0)) { + m_pulseaudio->process_events(); + } + } + } catch (const exception& err) { + m_log.err("%s: Failed to handle command (%s)", name(), err.what()); + } + + return true; + } +} + +POLYBAR_NS_END diff --git a/src/modules/volume.cpp b/src/modules/volume.cpp index 0fdf7101..1ce45df6 100644 --- a/src/modules/volume.cpp +++ b/src/modules/volume.cpp @@ -1,11 +1,7 @@ #include "modules/volume.hpp" -#if ENABLE_ALSA #include "adapters/alsa/control.hpp" #include "adapters/alsa/generic.hpp" #include "adapters/alsa/mixer.hpp" -#elif ENABLE_PULSEAUDIO -#include "adapters/pulseaudio.hpp" -#endif #include "drawtypes/label.hpp" #include "drawtypes/progressbar.hpp" #include "drawtypes/ramp.hpp" @@ -17,16 +13,13 @@ POLYBAR_NS -#if ENABLE_ALSA using namespace alsa; -#endif namespace modules { template class module; volume_module::volume_module(const bar_settings& bar, string name_) : event_module(bar, move(name_)) { // Load configuration values -#if ENABLE_ALSA m_mapped = m_conf.get(name(), "mapped", m_mapped); auto master_mixer_name = m_conf.get(name(), "master-mixer", "Master"s); @@ -73,14 +66,6 @@ namespace modules { } catch (const control_error& err) { throw module_error(err.what()); } -#elif ENABLE_PULSEAUDIO - auto sink_name = m_conf.get(name(), "sink", ""s); - try { - m_pulseaudio = factory_util::unique(move(sink_name)); - } catch (const pulseaudio_error& err) { - throw module_error(err.what()); - } -#endif // Add formats and elements m_formatter->add(FORMAT_VOLUME, TAG_LABEL_VOLUME, {TAG_RAMP_VOLUME, TAG_LABEL_VOLUME, TAG_BAR_VOLUME}); @@ -102,18 +87,13 @@ namespace modules { } void volume_module::teardown() { -#if ENABLE_ALSA m_mixer.clear(); m_ctrl.clear(); snd_config_update_free_global(); -#elif ENABLE_PULSEAUDIO - m_pulseaudio.reset(); -#endif } bool volume_module::has_event() { // Poll for mixer and control events -#if ENABLE_ALSA try { if (m_mixer[mixer::MASTER] && m_mixer[mixer::MASTER]->wait(25)) { return true; @@ -130,20 +110,12 @@ namespace modules { } catch (const alsa_exception& e) { m_log.err("%s: %s", name(), e.what()); } -#elif ENABLE_PULSEAUDIO - try { - if (m_pulseaudio->wait(25)) - return true; - } catch (const pulseaudio_error& e) { - m_log.err("%s: %s", name(), e.what()); - } -#endif + return false; } bool volume_module::update() { // Consume pending events -#if ENABLE_ALSA if (m_mixer[mixer::MASTER]) { m_mixer[mixer::MASTER]->process_events(); } @@ -156,16 +128,12 @@ namespace modules { if (m_ctrl[control::HEADPHONE]) { m_ctrl[control::HEADPHONE]->process_events(); } -#elif ENABLE_PULSEAUDIO - m_pulseaudio->process_events(); -#endif // Get volume, mute and headphone state m_volume = 100; m_muted = false; m_headphones = false; -#if ENABLE_ALSA try { if (m_mixer[mixer::MASTER]) { m_volume = m_volume * (m_mapped ? m_mixer[mixer::MASTER]->get_normalized_volume() / 100.0f @@ -196,16 +164,6 @@ namespace modules { } catch (const alsa_exception& err) { m_log.err("%s: Failed to query speaker mixer (%s)", name(), err.what()); } -#elif ENABLE_PULSEAUDIO - try { - if (m_pulseaudio) { - m_volume = m_volume * m_pulseaudio->get_volume() / 100.0f; - m_muted = m_muted || m_pulseaudio->is_muted(); - } - } catch (const pulseaudio_error& err) { - m_log.err("%s: Failed to query pulseaudio sink (%s)", name(), err.what()); - } -#endif // Replace label tokens if (m_label_volume) { @@ -264,14 +222,11 @@ namespace modules { return false; } else if (cmd.compare(0, 3, EVENT_PREFIX) != 0) { return false; -#if ENABLE_ALSA } else if (!m_mixer[mixer::MASTER]) { return false; -#endif } try { -#if ENABLE_ALSA vector mixers; bool headphones{m_headphones}; @@ -311,23 +266,6 @@ namespace modules { mixer->process_events(); } } -#elif ENABLE_PULSEAUDIO - if (m_pulseaudio && !m_pulseaudio->get_name().empty()) { - if (cmd.compare(0, strlen(EVENT_TOGGLE_MUTE), EVENT_TOGGLE_MUTE) == 0) { - m_pulseaudio->toggle_mute(); - } else if (cmd.compare(0, strlen(EVENT_VOLUME_UP), EVENT_VOLUME_UP) == 0) { - // cap above 100 (~150)? - m_pulseaudio->inc_volume(5); - } else if (cmd.compare(0, strlen(EVENT_VOLUME_DOWN), EVENT_VOLUME_DOWN) == 0) { - m_pulseaudio->inc_volume(-5); - } else { - return false; - } - if (m_pulseaudio->wait(0)) { - m_pulseaudio->process_events(); - } - } -#endif } catch (const exception& err) { m_log.err("%s: Failed to handle command (%s)", name(), err.what()); }