Implemented capture device selection for PulseAudio (marcelofg55)
This commit is contained in:
parent
0a877b58b8
commit
09eafaba62
@ -402,6 +402,26 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// User selected a new device, finish the current one so we'll init the new device
|
||||||
|
if (ad->capture_device_name != ad->capture_new_device) {
|
||||||
|
ad->capture_device_name = ad->capture_new_device;
|
||||||
|
ad->capture_finish_device();
|
||||||
|
|
||||||
|
Error err = ad->capture_init_device();
|
||||||
|
if (err != OK) {
|
||||||
|
ERR_PRINT("PulseAudio: capture_init_device error");
|
||||||
|
ad->capture_device_name = "Default";
|
||||||
|
ad->capture_new_device = "Default";
|
||||||
|
|
||||||
|
err = ad->capture_init_device();
|
||||||
|
if (err != OK) {
|
||||||
|
ad->active = false;
|
||||||
|
ad->exit_thread = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ad->stop_counting_ticks();
|
ad->stop_counting_ticks();
|
||||||
@ -540,11 +560,16 @@ void AudioDriverPulseAudio::finish() {
|
|||||||
thread = NULL;
|
thread = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error AudioDriverPulseAudio::capture_start() {
|
Error AudioDriverPulseAudio::capture_init_device() {
|
||||||
|
|
||||||
Error err = OK;
|
// If there is a specified device check that it is really present
|
||||||
|
if (capture_device_name != "Default") {
|
||||||
lock();
|
Array list = capture_get_device_list();
|
||||||
|
if (list.find(capture_device_name) == -1) {
|
||||||
|
capture_device_name = "Default";
|
||||||
|
capture_new_device = "Default";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pa_sample_spec spec;
|
pa_sample_spec spec;
|
||||||
|
|
||||||
@ -568,11 +593,12 @@ Error AudioDriverPulseAudio::capture_start() {
|
|||||||
ERR_FAIL_V(ERR_CANT_OPEN);
|
ERR_FAIL_V(ERR_CANT_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *dev = capture_device_name == "Default" ? NULL : capture_device_name.utf8().get_data();
|
||||||
pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE);
|
pa_stream_flags flags = pa_stream_flags(PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_ADJUST_LATENCY | PA_STREAM_AUTO_TIMING_UPDATE);
|
||||||
int error_code = pa_stream_connect_record(pa_rec_str, NULL, &attr, flags);
|
int error_code = pa_stream_connect_record(pa_rec_str, dev, &attr, flags);
|
||||||
if (error_code < 0) {
|
if (error_code < 0) {
|
||||||
ERR_PRINTS("PulseAudio: pa_stream_connect_record error: " + String(pa_strerror(error_code)));
|
ERR_PRINTS("PulseAudio: pa_stream_connect_record error: " + String(pa_strerror(error_code)));
|
||||||
err = ERR_CANT_OPEN;
|
ERR_FAIL_V(ERR_CANT_OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_input_buffer.resize(input_buffer_frames * 8);
|
audio_input_buffer.resize(input_buffer_frames * 8);
|
||||||
@ -581,21 +607,101 @@ Error AudioDriverPulseAudio::capture_start() {
|
|||||||
}
|
}
|
||||||
audio_input_position = 0;
|
audio_input_position = 0;
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDriverPulseAudio::capture_finish_device() {
|
||||||
|
|
||||||
|
if (pa_rec_str) {
|
||||||
|
int ret = pa_stream_disconnect(pa_rec_str);
|
||||||
|
if (ret != 0) {
|
||||||
|
ERR_PRINTS("PulseAudio: pa_stream_disconnect error: " + String(pa_strerror(ret)));
|
||||||
|
}
|
||||||
|
pa_stream_unref(pa_rec_str);
|
||||||
|
pa_rec_str = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error AudioDriverPulseAudio::capture_start() {
|
||||||
|
|
||||||
|
lock();
|
||||||
|
Error err = capture_init_device();
|
||||||
unlock();
|
unlock();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error AudioDriverPulseAudio::capture_stop() {
|
Error AudioDriverPulseAudio::capture_stop() {
|
||||||
if (pa_rec_str) {
|
lock();
|
||||||
pa_stream_disconnect(pa_rec_str);
|
capture_finish_device();
|
||||||
pa_stream_unref(pa_rec_str);
|
unlock();
|
||||||
pa_rec_str = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioDriverPulseAudio::capture_set_device(const String &p_name) {
|
||||||
|
|
||||||
|
lock();
|
||||||
|
capture_new_device = p_name;
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioDriverPulseAudio::pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata) {
|
||||||
|
AudioDriverPulseAudio *ad = (AudioDriverPulseAudio *)userdata;
|
||||||
|
|
||||||
|
// If eol is set to a positive number, you're at the end of the list
|
||||||
|
if (eol > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->monitor_of_sink == PA_INVALID_INDEX) {
|
||||||
|
ad->pa_rec_devices.push_back(l->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
ad->pa_status++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array AudioDriverPulseAudio::capture_get_device_list() {
|
||||||
|
|
||||||
|
pa_rec_devices.clear();
|
||||||
|
pa_rec_devices.push_back("Default");
|
||||||
|
|
||||||
|
if (pa_ctx == NULL) {
|
||||||
|
return pa_rec_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock();
|
||||||
|
|
||||||
|
// Get the device list
|
||||||
|
pa_status = 0;
|
||||||
|
pa_operation *pa_op = pa_context_get_source_info_list(pa_ctx, pa_sourcelist_cb, (void *)this);
|
||||||
|
if (pa_op) {
|
||||||
|
while (pa_status == 0) {
|
||||||
|
int ret = pa_mainloop_iterate(pa_ml, 1, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
ERR_PRINT("pa_mainloop_iterate error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pa_operation_unref(pa_op);
|
||||||
|
} else {
|
||||||
|
ERR_PRINT("pa_context_get_server_info error");
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
return pa_rec_devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
String AudioDriverPulseAudio::capture_get_device() {
|
||||||
|
|
||||||
|
lock();
|
||||||
|
String name = capture_device_name;
|
||||||
|
unlock();
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
AudioDriverPulseAudio::AudioDriverPulseAudio() {
|
AudioDriverPulseAudio::AudioDriverPulseAudio() {
|
||||||
|
|
||||||
pa_ml = NULL;
|
pa_ml = NULL;
|
||||||
|
@ -54,6 +54,10 @@ class AudioDriverPulseAudio : public AudioDriver {
|
|||||||
String new_device;
|
String new_device;
|
||||||
String default_device;
|
String default_device;
|
||||||
|
|
||||||
|
String capture_device_name;
|
||||||
|
String capture_new_device;
|
||||||
|
String capture_default_device;
|
||||||
|
|
||||||
Vector<int32_t> samples_in;
|
Vector<int32_t> samples_in;
|
||||||
Vector<int16_t> samples_out;
|
Vector<int16_t> samples_out;
|
||||||
|
|
||||||
@ -65,6 +69,7 @@ class AudioDriverPulseAudio : public AudioDriver {
|
|||||||
int pa_ready;
|
int pa_ready;
|
||||||
int pa_status;
|
int pa_status;
|
||||||
Array pa_devices;
|
Array pa_devices;
|
||||||
|
Array pa_rec_devices;
|
||||||
|
|
||||||
bool active;
|
bool active;
|
||||||
bool thread_exited;
|
bool thread_exited;
|
||||||
@ -76,10 +81,14 @@ class AudioDriverPulseAudio : public AudioDriver {
|
|||||||
static void pa_sink_info_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata);
|
static void pa_sink_info_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata);
|
||||||
static void pa_server_info_cb(pa_context *c, const pa_server_info *i, void *userdata);
|
static void pa_server_info_cb(pa_context *c, const pa_server_info *i, void *userdata);
|
||||||
static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata);
|
static void pa_sinklist_cb(pa_context *c, const pa_sink_info *l, int eol, void *userdata);
|
||||||
|
static void pa_sourcelist_cb(pa_context *c, const pa_source_info *l, int eol, void *userdata);
|
||||||
|
|
||||||
Error init_device();
|
Error init_device();
|
||||||
void finish_device();
|
void finish_device();
|
||||||
|
|
||||||
|
Error capture_init_device();
|
||||||
|
void capture_finish_device();
|
||||||
|
|
||||||
void detect_channels();
|
void detect_channels();
|
||||||
|
|
||||||
static void thread_func(void *p_udata);
|
static void thread_func(void *p_udata);
|
||||||
@ -93,9 +102,15 @@ public:
|
|||||||
virtual void start();
|
virtual void start();
|
||||||
virtual int get_mix_rate() const;
|
virtual int get_mix_rate() const;
|
||||||
virtual SpeakerMode get_speaker_mode() const;
|
virtual SpeakerMode get_speaker_mode() const;
|
||||||
|
|
||||||
virtual Array get_device_list();
|
virtual Array get_device_list();
|
||||||
virtual String get_device();
|
virtual String get_device();
|
||||||
virtual void set_device(String device);
|
virtual void set_device(String device);
|
||||||
|
|
||||||
|
virtual Array capture_get_device_list();
|
||||||
|
virtual void capture_set_device(const String &p_name);
|
||||||
|
virtual String capture_get_device();
|
||||||
|
|
||||||
virtual void lock();
|
virtual void lock();
|
||||||
virtual void unlock();
|
virtual void unlock();
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
Loading…
Reference in New Issue
Block a user