From 7f47a444d65df6c17fc07a23664ad1d8ccc4f00b Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 19 Jun 2018 14:13:01 +0900 Subject: [PATCH] Add feature list available sinks/sources --- CMakeLists.txt | 3 +- Changelog.md | 5 ++ src/Main.cpp | 15 ++++ src/MfPA/GetSinkSourceInfo.cpp | 121 +++++++++++++++++++++++++++++++++ src/MfPA/GetSinkSourceInfo.hpp | 44 ++++++++++++ src/MfPA/Meter.cpp | 3 +- 6 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 src/MfPA/GetSinkSourceInfo.cpp create mode 100644 src/MfPA/GetSinkSourceInfo.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c9bb006..9575e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,11 +1,12 @@ cmake_minimum_required(VERSION 3.0) -project(MeterForPulseAudio VERSION 1.2) +project(MeterForPulseAudio VERSION 1.3) set(MeterForPulseAudio_SOURCES GameDevTools/src/GDT/GameLoop.cpp src/Main.cpp src/MfPA/Meter.cpp + src/MfPA/GetSinkSourceInfo.cpp ) # check if submodules are loaded diff --git a/Changelog.md b/Changelog.md index 2195dfc..d99e78a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,8 @@ +# Version 1.3 + +Added feature to print available sinks/sources (invoked via arguments to +program). + # Version 1.2 Improved error output when failed getting info on sink/source. diff --git a/src/Main.cpp b/src/Main.cpp index 0073d1a..4c45a2e 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -6,6 +6,7 @@ #include #include "MfPA/Meter.hpp" +#include "MfPA/GetSinkSourceInfo.hpp" int main(int argc, char** argv) { @@ -86,6 +87,20 @@ int main(int argc, char** argv) }, "Sets the bar color to a specified color (hex input like 0xFFFFFF, " "red is most significant byte out of 3)"); + parser.addLongFlag("list-sinks", + [] () { + MfPA::GetSinkSourceInfo getInfo(true); + getInfo.startMainLoop(); + std::exit(0); + }, + "Lists available PulseAudio sinks"); + parser.addLongFlag("list-sources", + [] () { + MfPA::GetSinkSourceInfo getInfo(false); + getInfo.startMainLoop(); + std::exit(0); + }, + "Lists available PulseAudio sources"); parser.addFlag( "h", [&parser] () { diff --git a/src/MfPA/GetSinkSourceInfo.cpp b/src/MfPA/GetSinkSourceInfo.cpp new file mode 100644 index 0000000..3aa9fc0 --- /dev/null +++ b/src/MfPA/GetSinkSourceInfo.cpp @@ -0,0 +1,121 @@ +#include "GetSinkSourceInfo.hpp" + +#include + +#include + +MfPA::GetSinkSourceInfo::GetSinkSourceInfo(bool getSinkInfo) : +getSinkInfo(getSinkInfo), +isReady(false), +run(true) +{ + mainLoop = pa_mainloop_new(); + context = pa_context_new( + pa_mainloop_get_api(mainLoop), "Get Pulse Sink/Source Info"); + pa_context_set_state_callback( + context, + MfPA::GetSinkSourceInfo::get_state_callback, + this); + pa_context_connect(context, nullptr, PA_CONTEXT_NOFLAGS, nullptr); +} + +MfPA::GetSinkSourceInfo::~GetSinkSourceInfo() +{ + if(context) + { + pa_context_disconnect(context); + pa_context_unref(context); + } + + if(mainLoop) + { + pa_mainloop_free(mainLoop); + } +} + +void MfPA::GetSinkSourceInfo::get_state_callback(pa_context* c, void* userdata) +{ + MfPA::GetSinkSourceInfo* getInfo = (MfPA::GetSinkSourceInfo*) userdata; + switch(pa_context_get_state(c)) + { + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + case PA_CONTEXT_READY: + getInfo->isReady = true; + if(getInfo->getSinkInfo) + { + std::cout << "Available sinks:" << std::endl; + pa_operation_unref(pa_context_get_sink_info_list( + c, + MfPA::GetSinkSourceInfo::get_sink_info_callback, + userdata)); + } + else + { + std::cout << "Available sources:" << std::endl; + pa_operation_unref(pa_context_get_source_info_list( + c, + MfPA::GetSinkSourceInfo::get_source_info_callback, + userdata)); + } + break; + case PA_CONTEXT_FAILED: + std::cerr << "ERROR during context state callback: " + << pa_strerror(pa_context_errno(c)) << std::endl; + case PA_CONTEXT_TERMINATED: + getInfo->run = false; + break; + } +} + +void MfPA::GetSinkSourceInfo::get_sink_info_callback( + pa_context* c, + const pa_sink_info* i, + int eol, + void* userdata) +{ +// MfPA::GetSinkSourceInfo* getInfo = (MfPA::GetSinkSourceInfo*) userdata; + if(eol != PA_OK) + { + return; + } + std::cout << " " << i->name << std::endl; +} + +void MfPA::GetSinkSourceInfo::get_source_info_callback( + pa_context* c, + const pa_source_info* i, + int eol, + void* userdata) +{ +// MfPA::GetSinkSourceInfo* getInfo = (MfPA::GetSinkSourceInfo*) userdata; + if(eol != PA_OK) + { + return; + } + std::cout << " " << i->name << std::endl; +} + +void MfPA::GetSinkSourceInfo::startMainLoop() +{ + float timer = GET_SINK_SOURCE_INFO_ITERATION_TIME; + GDT::IntervalBasedGameLoop( + &run, + [this, &timer] (float dt) { + pa_mainloop_iterate(mainLoop, 0, nullptr); + if(isReady) + { + timer -= dt; + if(timer <= 0.0f) + { + run = false; + } + } + }, + [] () {}, + 60, + 1.0f / 120.0f); +} diff --git a/src/MfPA/GetSinkSourceInfo.hpp b/src/MfPA/GetSinkSourceInfo.hpp new file mode 100644 index 0000000..b9110df --- /dev/null +++ b/src/MfPA/GetSinkSourceInfo.hpp @@ -0,0 +1,44 @@ +#ifndef GET_SINK_SOURCE_INFO_HPP +#define GET_SINK_SOURCE_INFO_HPP + +#define GET_SINK_SOURCE_INFO_ITERATION_TIME 1.0f + +#include + +namespace MfPA +{ + +class GetSinkSourceInfo +{ +public: + GetSinkSourceInfo(bool getSinkInfo); + ~GetSinkSourceInfo(); + + static void get_state_callback(pa_context* c, void* userdata); + static void get_sink_info_callback( + pa_context* c, + const pa_sink_info* i, + int eol, + void* userdata); + static void get_source_info_callback( + pa_context* c, + const pa_source_info* i, + int eol, + void* userdata); + + void startMainLoop(); + +private: + bool getSinkInfo; + + pa_mainloop* mainLoop; + pa_context* context; + bool isReady; + + bool run; + +}; + +} // namespace MfPA + +#endif diff --git a/src/MfPA/Meter.cpp b/src/MfPA/Meter.cpp index b907b41..7933942 100644 --- a/src/MfPA/Meter.cpp +++ b/src/MfPA/Meter.cpp @@ -34,7 +34,8 @@ barColor(barColor) setenv("PULSE_PROP_application.icon_name", "multimedia-volume-control", 1); mainLoop = pa_mainloop_new(); - context = pa_context_new(pa_mainloop_get_api(mainLoop), "Meter for PulseAudio"); + context = pa_context_new( + pa_mainloop_get_api(mainLoop), "Meter for PulseAudio"); pa_context_set_state_callback( context, MfPA::Meter::get_context_callback, -- 2.49.0