mirror of
https://github.com/clangen/musikcube.git
synced 2025-01-16 22:13:19 +00:00
Added an alternate method for setting volume in PulseOut.
This commit is contained in:
parent
b8a220e1dd
commit
9c30e0e7f6
@ -8,7 +8,7 @@ cmake_minimum_required(VERSION 3.0)
|
||||
project(musikbox)
|
||||
set (musikbox_VERSION_MAJOR 0)
|
||||
set (musikbox_VERSION_MINOR 9)
|
||||
set (musikbox_VERSION_PATCH 3)
|
||||
set (musikbox_VERSION_PATCH 4)
|
||||
set (musikbox_VERSION "${musikbox_VERSION_MAJOR}.${musikbox_VERSION_MINOR}.${musikbox_VERSION_PATCH}")
|
||||
|
||||
include(ExternalProject)
|
||||
|
@ -34,12 +34,20 @@
|
||||
|
||||
#include "PulseOut.h"
|
||||
#include <core/sdk/constants.h>
|
||||
#include <core/sdk/IPreferences.h>
|
||||
#include <pulse/volume.h>
|
||||
#include <math.h>
|
||||
|
||||
using namespace musik::core::sdk;
|
||||
|
||||
typedef std::unique_lock<std::recursive_mutex> Lock;
|
||||
static musik::core::sdk::IPreferences* prefs = nullptr;
|
||||
|
||||
extern "C" void SetPreferences(musik::core::sdk::IPreferences* prefs) {
|
||||
::prefs = prefs;
|
||||
prefs->GetBool("force_sw_volume", false);
|
||||
prefs->Save();
|
||||
}
|
||||
|
||||
PulseOut::PulseOut() {
|
||||
std::cerr << "PulseOut::PulseOut() called" << std::endl;
|
||||
@ -49,6 +57,7 @@ PulseOut::PulseOut() {
|
||||
this->volumeUpdated = false;
|
||||
this->channels = 0;
|
||||
this->rate = 0;
|
||||
this->hwVolume = false;
|
||||
}
|
||||
|
||||
PulseOut::~PulseOut() {
|
||||
@ -105,10 +114,16 @@ void PulseOut::OpenDevice(musik::core::sdk::IBuffer* buffer) {
|
||||
0);
|
||||
|
||||
if (this->audioConnection) {
|
||||
this->SetVolume(this->volume);
|
||||
this->rate = buffer->SampleRate();
|
||||
this->channels = buffer->Channels();
|
||||
this->state = StatePlaying;
|
||||
|
||||
this->hwVolume = pa_blocking_has_hw_volume(this->audioConnection, 0);
|
||||
if (::prefs && ::prefs->GetBool("force_sw_volume", false)) {
|
||||
this->hwVolume = false;
|
||||
}
|
||||
|
||||
this->SetVolume(this->volume);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,9 +163,17 @@ void PulseOut::SetVolume(double volume) {
|
||||
this->volume = volume;
|
||||
this->volumeUpdated = false;
|
||||
if (this->audioConnection) {
|
||||
int normalized = (int) round((double) PA_VOLUME_NORM * volume);
|
||||
int normalized;
|
||||
if (this->hwVolume) {
|
||||
//std::cerr << "PulseOut: hw volume!\n";
|
||||
normalized = (int) round((double) PA_VOLUME_NORM * volume);
|
||||
}
|
||||
else {
|
||||
//std::cerr << "PulseOut: sw volume!\n";
|
||||
normalized = (int) pa_sw_volume_from_linear(this->volume);
|
||||
}
|
||||
this->volumeUpdated = pa_blocking_set_volume(this->audioConnection, normalized, 0) == 0;
|
||||
std::cerr << "PulseOut: volumeUpdated = " << this->volumeUpdated << "\n";
|
||||
//std::cerr << "PulseOut: volumeUpdated = " << this->volumeUpdated << ", value = " << normalized << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,4 +77,5 @@ class PulseOut : public musik::core::sdk::IOutput {
|
||||
int channels, rate;
|
||||
double volume;
|
||||
bool volumeUpdated;
|
||||
bool hwVolume;
|
||||
};
|
||||
|
@ -42,6 +42,8 @@ struct pa_blocking {
|
||||
const void *read_data;
|
||||
size_t read_index, read_length;
|
||||
size_t channels;
|
||||
int sink_id;
|
||||
int hw_volume;
|
||||
|
||||
int operation_success;
|
||||
};
|
||||
@ -165,6 +167,8 @@ pa_blocking* pa_blocking_new(
|
||||
p = pa_xnew0(pa_blocking, 1);
|
||||
p->direction = dir;
|
||||
p->channels = ss->channels;
|
||||
p->sink_id = -1;
|
||||
p->hw_volume = -1;
|
||||
|
||||
if (!(p->mainloop = pa_threaded_mainloop_new()))
|
||||
goto fail;
|
||||
@ -551,3 +555,94 @@ unlock_and_fail:
|
||||
pa_threaded_mainloop_unlock(p->mainloop);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void sink_info_cb(pa_context* c, const pa_sink_info* info, int eol, void* userdata) {
|
||||
pa_blocking* p = (pa_blocking*) userdata;
|
||||
|
||||
if (info) {
|
||||
p->hw_volume = (info->flags & PA_SINK_HW_VOLUME_CTRL) != 0;
|
||||
p->operation_success = 1;
|
||||
pa_threaded_mainloop_signal(p->mainloop, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void sink_input_info_cb(pa_context* c, const pa_sink_input_info* info, int eol, void* userdata) {
|
||||
pa_blocking* p = (pa_blocking*) userdata;
|
||||
|
||||
if (info) {
|
||||
p->sink_id = info->sink;
|
||||
p->operation_success = 1;
|
||||
pa_threaded_mainloop_signal(p->mainloop, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int pa_blocking_has_hw_volume(pa_blocking *p, int *rerror) {
|
||||
pa_operation *o = NULL;
|
||||
pa_stream *s = NULL;
|
||||
uint32_t idx;
|
||||
int result = -1;
|
||||
int sink = -1;
|
||||
|
||||
assert(p);
|
||||
|
||||
if (p->hw_volume != -1) {
|
||||
return p->hw_volume;
|
||||
}
|
||||
|
||||
CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
|
||||
|
||||
pa_threaded_mainloop_lock(p->mainloop);
|
||||
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
|
||||
|
||||
CHECK_SUCCESS_GOTO(p, rerror, ((idx = pa_stream_get_index (p->stream)) != PA_INVALID_INDEX), unlock_and_fail);
|
||||
|
||||
s = p->stream;
|
||||
assert(s);
|
||||
|
||||
/* determine the sink id */
|
||||
if (p->sink_id == -1) {
|
||||
o = pa_context_get_sink_input_info(p->context, idx, sink_input_info_cb, p);
|
||||
|
||||
CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
|
||||
p->operation_success = 0;
|
||||
while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
|
||||
pa_threaded_mainloop_wait(p->mainloop);
|
||||
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
|
||||
}
|
||||
CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
|
||||
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "success getting sink_id=%d\n", p->sink_id);
|
||||
|
||||
if (p->sink_id != -1) {
|
||||
/* once we have the sink id, query it for hw volume info */
|
||||
o = pa_context_get_sink_info_by_index(p->context, p->sink_id, sink_info_cb, p);
|
||||
|
||||
CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
|
||||
p->operation_success = 0;
|
||||
while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
|
||||
pa_threaded_mainloop_wait(p->mainloop);
|
||||
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
|
||||
}
|
||||
CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
|
||||
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
//fprintf(stderr, "success getting hw_volume=%d\n", p->hw_volume);
|
||||
|
||||
pa_threaded_mainloop_unlock(p->mainloop);
|
||||
return p->hw_volume == -1 ? 0 : p->hw_volume;
|
||||
|
||||
unlock_and_fail:
|
||||
|
||||
if (o) {
|
||||
pa_operation_cancel(o);
|
||||
pa_operation_unref(o);
|
||||
}
|
||||
|
||||
pa_threaded_mainloop_unlock(p->mainloop);
|
||||
return 0;
|
||||
}
|
||||
|
@ -78,5 +78,8 @@ int pa_blocking_flush(pa_blocking *s, int *error);
|
||||
/** Set the output volume of the stream. */
|
||||
int pa_blocking_set_volume(pa_blocking *p, int volume, int *rerror);
|
||||
|
||||
/** returns 1 if the stream has hardware volume, false otherwise */
|
||||
int pa_blocking_has_hw_volume(pa_blocking *p, int *rerror);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
|
@ -44,7 +44,7 @@ class PulsePlugin : public musik::core::sdk::IPlugin {
|
||||
public:
|
||||
virtual void Destroy() { delete this; }
|
||||
virtual const char* Name() { return "PulseAudio IOutput"; }
|
||||
virtual const char* Version() { return "0.3"; }
|
||||
virtual const char* Version() { return "0.4.0"; }
|
||||
virtual const char* Author() { return "clangen"; }
|
||||
virtual int SdkVersion() { return musik::core::sdk::SdkVersion; }
|
||||
};
|
||||
|
@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION "0.9.3"
|
||||
#define VERSION "0.9.4"
|
||||
|
Loading…
Reference in New Issue
Block a user