mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2026-08-26 18:45:10 -05:00
Add ability to choose audio output device via a menu
This commit is contained in:
@@ -489,7 +489,7 @@ if(MSVC)
|
||||
else()
|
||||
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$<CONFIG:Release>:-O3>")
|
||||
endif()
|
||||
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
|
||||
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
|
||||
|
||||
|
||||
if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL ""))
|
||||
|
||||
31
include/Menus/AudioDeviceMenu.hpp
Normal file
31
include/Menus/AudioDeviceMenu.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __AUDIODEVICEMENU_HPP
|
||||
#define __AUDIODEVICEMENU_HPP
|
||||
|
||||
#include "OptionSelectionMenu.hpp"
|
||||
#include <chrono>
|
||||
|
||||
#include "TextRectangle.hpp"
|
||||
#include "sfml_gfx_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "audio_data.hpp"
|
||||
|
||||
#define AUDIODEVICE_MENU_NO_ACTION -1
|
||||
#define AUDIODEVICE_MENU_BACK -2
|
||||
|
||||
class AudioDeviceMenu : public OptionSelectionMenu {
|
||||
public:
|
||||
AudioDeviceMenu(bool font_load_success, sf::Font &text_font);
|
||||
~AudioDeviceMenu();
|
||||
void prepare(float scaling_factor, int view_size_x, int view_size_y, const audio_output_device_data curr_device_data);
|
||||
void insert_data(std::vector<std::string>* possible_devices);
|
||||
int selected_index = AUDIODEVICE_MENU_NO_ACTION;
|
||||
void reset_output_option();
|
||||
protected:
|
||||
void set_output_option(int index, int action);
|
||||
int get_num_options();
|
||||
std::string get_string_option(int index, int action);
|
||||
void class_setup();
|
||||
private:
|
||||
std::vector<std::string>* possible_devices;
|
||||
};
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@ enum AudioMenuOutAction{
|
||||
AUDIO_MENU_OUTPUT_DEC,
|
||||
AUDIO_MENU_OUTPUT_INC,
|
||||
AUDIO_MENU_RESTART,
|
||||
AUDIO_MENU_NEXT_DEVICE,
|
||||
AUDIO_MENU_CHANGE_DEVICE,
|
||||
};
|
||||
|
||||
class AudioMenu : public OptionSelectionMenu {
|
||||
|
||||
@@ -2,10 +2,18 @@
|
||||
#define __AUDIO_DATA_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#define MAX_MAX_AUDIO_LATENCY 10
|
||||
|
||||
enum AudioOutputType {AUDIO_OUTPUT_STEREO, AUDIO_OUTPUT_MONO, AUDIO_OUTPUT_END};
|
||||
|
||||
struct audio_output_device_data {
|
||||
bool preference_requested = false;
|
||||
std::string preferred = "";
|
||||
};
|
||||
|
||||
int searchAudioDevice(std::string device_name, std::vector<std::string> &audio_devices);
|
||||
|
||||
class AudioData {
|
||||
public:
|
||||
void reset();
|
||||
@@ -27,12 +35,15 @@ public:
|
||||
bool load_audio_data(std::string key, std::string value);
|
||||
std::string save_audio_data();
|
||||
void set_audio_volume(int new_volume);
|
||||
audio_output_device_data get_audio_output_device_data();
|
||||
void set_audio_output_device_data(audio_output_device_data new_device_data);
|
||||
|
||||
private:
|
||||
int volume;
|
||||
int max_audio_latency;
|
||||
bool mute;
|
||||
AudioOutputType output_type;
|
||||
audio_output_device_data output_device;
|
||||
bool restart_request = false;
|
||||
bool text_updated;
|
||||
std::string text;
|
||||
@@ -44,6 +55,8 @@ private:
|
||||
const std::string volume_str = "volume";
|
||||
const std::string mute_str = "mute";
|
||||
const std::string output_type_str = "audio_output_type";
|
||||
const std::string device_request_str = "audio_output_device_requested";
|
||||
const std::string device_name_str = "audio_output_device_name";
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
enum ScreenType { TOP, BOTTOM, JOINT };
|
||||
enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END };
|
||||
enum NonIntegerScalingModes { SMALLER_PRIORITY, INVERSE_PROPORTIONAL_PRIORITY, EQUAL_PRIORITY, PROPORTIONAL_PRIORITY, BIGGER_PRIORITY, END_NONINT_SCALE_MODES };
|
||||
enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE };
|
||||
enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE, AUDIO_DEVICE_MENU_TYPE };
|
||||
enum InputColorspaceMode { FULL_COLORSPACE, DS_COLORSPACE, GBA_COLORSPACE, INPUT_COLORSPACE_END };
|
||||
enum FrameBlendingMode { NO_FRAME_BLENDING, FULL_FRAME_BLENDING, DS_3D_BOTH_SCREENS_FRAME_BLENDING, FRAME_BLENDING_END };
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "ISNitroMenu.hpp"
|
||||
#include "VideoEffectsMenu.hpp"
|
||||
#include "InputMenu.hpp"
|
||||
#include "AudioDeviceMenu.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "event_structs.hpp"
|
||||
#include "shaders_list.hpp"
|
||||
@@ -153,12 +154,14 @@ private:
|
||||
ScalingRatioMenu *scaling_ratio_menu;
|
||||
VideoEffectsMenu *video_effects_menu;
|
||||
InputMenu *input_menu;
|
||||
AudioDeviceMenu *audio_device_menu;
|
||||
std::vector<const CropData*> possible_crops;
|
||||
std::vector<const CropData*> possible_crops_ds;
|
||||
std::vector<const CropData*> possible_crops_with_games;
|
||||
std::vector<const CropData*> possible_crops_ds_with_games;
|
||||
std::vector<const PARData*> possible_pars;
|
||||
std::vector<sf::VideoMode> possible_resolutions;
|
||||
std::vector<std::string> possible_audio_devices;
|
||||
std::vector<FileData> possible_files;
|
||||
std::vector<std::string> possible_buttons_names;
|
||||
std::vector<const WindowCommand **> possible_buttons_ptrs;
|
||||
@@ -226,6 +229,7 @@ private:
|
||||
void fast_poll_change();
|
||||
void padding_change();
|
||||
void game_crop_enable_change();
|
||||
void audio_device_change(audio_output_device_data new_device_data);
|
||||
void is_nitro_capture_type_change(bool positive);
|
||||
void is_nitro_capture_speed_change(bool positive);
|
||||
void is_nitro_capture_reset_hw();
|
||||
@@ -299,6 +303,7 @@ private:
|
||||
void setup_bfi_menu(bool reset_data = true);
|
||||
void setup_fileconfig_menu(bool is_save, bool reset_data = true, bool skip_setup_check = false);
|
||||
void setup_resolution_menu(bool reset_data = true);
|
||||
void setup_audio_devices_menu(bool reset_data = true);
|
||||
void setup_extra_menu(bool reset_data = true);
|
||||
void setup_shortcuts_menu(bool reset_data = true);
|
||||
void setup_action_selection_menu(bool reset_data = true);
|
||||
|
||||
@@ -262,6 +262,8 @@ static void cypress_device_read_frame_cb(void* user_data, int transfer_length, i
|
||||
if((*cypress_device_capture_recv_data->consecutive_output_to_thread) > NUM_CONSECUTIVE_NEEDED_OUTPUT)
|
||||
*cypress_device_capture_recv_data->errors_since_last_output = 0;
|
||||
*cypress_device_capture_recv_data->last_index = cypress_device_capture_recv_data->index;
|
||||
|
||||
// Realign, with multiple of max_usb_packet_size
|
||||
if((*cypress_device_capture_recv_data->is_active_special_read) && (((int32_t)(cypress_device_capture_recv_data->index - (*cypress_device_capture_recv_data->active_special_read_index))) >= 0)) {
|
||||
*cypress_device_capture_recv_data->is_active_special_read = false;
|
||||
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data);
|
||||
@@ -394,6 +396,12 @@ void reset_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_devic
|
||||
}
|
||||
|
||||
void recalibration_reads(cyni_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressDeviceCaptureReceivedData* chosen_buffer, uint32_t &index, CaptureScreensType curr_capture_type) {
|
||||
// Enforce properly synchronized reads.
|
||||
// Reduces complexity and latency, at the cost of some extra
|
||||
// time between lid reopening and visible video output.
|
||||
// For differences which are multiple of max_usb_packet_size,
|
||||
// regular reads can be used. For non-multiples, use this,
|
||||
// which adds sleeps to better align.
|
||||
CaptureData* capture_data = cypress_device_capture_recv_data[0].capture_data;
|
||||
do {
|
||||
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
|
||||
|
||||
71
source/Menus/AudioDeviceMenu.cpp
Normal file
71
source/Menus/AudioDeviceMenu.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "AudioDeviceMenu.hpp"
|
||||
|
||||
AudioDeviceMenu::AudioDeviceMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
|
||||
this->initialize(font_load_success, text_font);
|
||||
}
|
||||
|
||||
AudioDeviceMenu::~AudioDeviceMenu() {
|
||||
}
|
||||
|
||||
void AudioDeviceMenu::class_setup() {
|
||||
this->num_options_per_screen = 5;
|
||||
this->min_elements_text_scaling_factor = num_options_per_screen + 2;
|
||||
this->width_factor_menu = 16;
|
||||
this->width_divisor_menu = 9;
|
||||
this->base_height_factor_menu = 12;
|
||||
this->base_height_divisor_menu = 6;
|
||||
this->min_text_size = 0.3;
|
||||
this->max_width_slack = 1.1;
|
||||
this->menu_color = sf::Color(30, 30, 60, 192);
|
||||
this->title = "Audio Device Selection";
|
||||
this->show_back_x = true;
|
||||
this->show_x = false;
|
||||
this->show_title = true;
|
||||
}
|
||||
|
||||
void AudioDeviceMenu::insert_data(std::vector<std::string>* possible_devices) {
|
||||
this->possible_devices = possible_devices;
|
||||
this->prepare_options();
|
||||
}
|
||||
|
||||
void AudioDeviceMenu::reset_output_option() {
|
||||
this->selected_index = AUDIODEVICE_MENU_NO_ACTION;
|
||||
}
|
||||
|
||||
void AudioDeviceMenu::set_output_option(int index, int action) {
|
||||
if(index == BACK_X_OUTPUT_OPTION)
|
||||
this->selected_index = AUDIODEVICE_MENU_BACK;
|
||||
else
|
||||
this->selected_index = index;
|
||||
}
|
||||
|
||||
int AudioDeviceMenu::get_num_options() {
|
||||
return this->possible_devices->size() + 1;
|
||||
}
|
||||
|
||||
std::string AudioDeviceMenu::get_string_option(int index, int action) {
|
||||
if(index == 0)
|
||||
return "System Preference";
|
||||
return (*this->possible_devices)[index - 1];
|
||||
}
|
||||
|
||||
void AudioDeviceMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, const audio_output_device_data curr_device_data) {
|
||||
int num_pages = this->get_num_pages();
|
||||
if(this->future_data.page >= num_pages)
|
||||
this->future_data.page = num_pages - 1;
|
||||
int start = this->future_data.page * this->num_options_per_screen;
|
||||
for(int i = 0; i < this->num_options_per_screen + 1; i++) {
|
||||
int index = (i * this->single_option_multiplier) + this->elements_start_id;
|
||||
if(!this->future_enabled_labels[index])
|
||||
continue;
|
||||
int mode_index = start + i;
|
||||
int device_index = -1;
|
||||
if(curr_device_data.preference_requested)
|
||||
device_index = searchAudioDevice(curr_device_data.preferred, *this->possible_devices);
|
||||
if(mode_index == (device_index + 1))
|
||||
this->labels[index]->setText("< " + this->get_string_option(mode_index, DEFAULT_ACTION) + " >");
|
||||
else
|
||||
this->labels[index]->setText(this->get_string_option(mode_index, DEFAULT_ACTION));
|
||||
}
|
||||
this->base_prepare(menu_scaling_factor, view_size_x, view_size_y);
|
||||
}
|
||||
@@ -40,9 +40,9 @@ static const AudioMenuOptionInfo audio_restart_option = {
|
||||
.out_action = AUDIO_MENU_RESTART};
|
||||
|
||||
static const AudioMenuOptionInfo audio_next_device_option = {
|
||||
.base_name = "Output Device", .false_name = "",
|
||||
.base_name = "Select Output Device", .false_name = "",
|
||||
.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = AUDIO_MENU_NO_ACTION,
|
||||
.out_action = AUDIO_MENU_NEXT_DEVICE};
|
||||
.out_action = AUDIO_MENU_CHANGE_DEVICE};
|
||||
|
||||
|
||||
static const AudioMenuOptionInfo* pollable_options[] = {
|
||||
@@ -50,8 +50,8 @@ static const AudioMenuOptionInfo* pollable_options[] = {
|
||||
&audio_mute_option,
|
||||
&audio_max_latency_option,
|
||||
&audio_output_type_option,
|
||||
&audio_restart_option,
|
||||
&audio_next_device_option,
|
||||
&audio_restart_option,
|
||||
};
|
||||
|
||||
AudioMenu::AudioMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
|
||||
@@ -144,11 +144,6 @@ void AudioMenu::prepare(float menu_scaling_factor, int view_size_x, int view_siz
|
||||
case AUDIO_MENU_MUTE:
|
||||
this->labels[index]->setText(this->setTextOptionBool(real_index, audio_data->get_mute()));
|
||||
break;
|
||||
case AUDIO_MENU_NEXT_DEVICE:
|
||||
if (std::optional<std::string> cur_dev = sf::PlaybackDevice::getDevice()) {
|
||||
this->labels[index]->setText(this->setTextOptionString(real_index, *cur_dev));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ void WindowScreen::init_menus() {
|
||||
this->is_nitro_menu = new ISNitroMenu(this->font_load_success, this->text_font);
|
||||
this->video_effects_menu = new VideoEffectsMenu(this->font_load_success, this->text_font);
|
||||
this->input_menu = new InputMenu(this->font_load_success, this->text_font);
|
||||
this->audio_device_menu = new AudioDeviceMenu(this->font_load_success, this->text_font);
|
||||
}
|
||||
|
||||
void WindowScreen::destroy_menus() {
|
||||
@@ -139,6 +140,7 @@ void WindowScreen::destroy_menus() {
|
||||
delete this->is_nitro_menu;
|
||||
delete this->video_effects_menu;
|
||||
delete this->input_menu;
|
||||
delete this->audio_device_menu;
|
||||
}
|
||||
|
||||
void WindowScreen::set_close(int ret_val) {
|
||||
@@ -289,6 +291,11 @@ void WindowScreen::offset_change(float &value, float change) {
|
||||
this->future_operations.call_screen_settings_update = true;
|
||||
}
|
||||
|
||||
void WindowScreen::audio_device_change(audio_output_device_data new_device_data) {
|
||||
this->audio_data->set_audio_output_device_data(new_device_data);
|
||||
this->print_notification("Audio device changed");
|
||||
}
|
||||
|
||||
void WindowScreen::menu_scaling_change(bool positive) {
|
||||
double old_scaling = this->m_info.menu_scaling_factor;
|
||||
if(positive)
|
||||
@@ -694,6 +701,20 @@ void WindowScreen::setup_input_menu(bool reset_data) {
|
||||
}
|
||||
}
|
||||
|
||||
void WindowScreen::setup_audio_devices_menu(bool reset_data){
|
||||
if(!this->can_setup_menu())
|
||||
return;
|
||||
if(this->curr_menu != AUDIO_DEVICE_MENU_TYPE) {
|
||||
this->possible_audio_devices.clear();
|
||||
this->possible_audio_devices = sf::PlaybackDevice::getAvailableDevices();
|
||||
this->curr_menu = AUDIO_DEVICE_MENU_TYPE;
|
||||
if(reset_data)
|
||||
this->audio_device_menu->reset_data();
|
||||
this->audio_device_menu->insert_data(&this->possible_audio_devices);
|
||||
this->last_menu_change_time = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowScreen::setup_video_menu(bool reset_data) {
|
||||
if(!this->can_setup_menu())
|
||||
return;
|
||||
@@ -1374,24 +1395,9 @@ void WindowScreen::poll(bool do_everything) {
|
||||
case AUDIO_MENU_RESTART:
|
||||
this->audio_data->request_audio_restart();
|
||||
break;
|
||||
case AUDIO_MENU_NEXT_DEVICE:
|
||||
if (std::optional<std::string> cur_dev = sf::PlaybackDevice::getDevice()) {
|
||||
std::cout << *cur_dev << std::endl;
|
||||
int idx = 0;
|
||||
auto audio_devices = sf::PlaybackDevice::getAvailableDevices();
|
||||
for (const std::string& device : audio_devices) {
|
||||
if (device == *cur_dev) {
|
||||
break;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
idx = std::max((idx + 1) % static_cast<int>(audio_devices.size()), 0);
|
||||
std::cout << "next device: " << audio_devices.at(idx) << std::endl;
|
||||
if (sf::PlaybackDevice::setDevice(audio_devices.at(idx))) {
|
||||
std::cout << "Device selected: " << audio_devices.at(idx) << std::endl;
|
||||
// this->audio_data->request_audio_restart();
|
||||
}
|
||||
}
|
||||
case AUDIO_MENU_CHANGE_DEVICE:
|
||||
this->setup_audio_devices_menu();
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1984,6 +1990,29 @@ void WindowScreen::poll(bool do_everything) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case AUDIO_DEVICE_MENU_TYPE:
|
||||
if(this->audio_device_menu->poll(event_data)) {
|
||||
switch(this->audio_device_menu->selected_index) {
|
||||
case AUDIODEVICE_MENU_BACK:
|
||||
this->setup_audio_menu(false);
|
||||
done = true;
|
||||
break;
|
||||
case AUDIODEVICE_MENU_NO_ACTION:
|
||||
break;
|
||||
default:
|
||||
audio_output_device_data tmp_out_device;
|
||||
int output_device_index = this->audio_device_menu->selected_index - 1;
|
||||
if((output_device_index >= 0) && (output_device_index < this->possible_audio_devices.size())) {
|
||||
tmp_out_device.preference_requested = true;
|
||||
tmp_out_device.preferred = this->possible_audio_devices[output_device_index];
|
||||
}
|
||||
this->audio_device_change(tmp_out_device);
|
||||
break;
|
||||
}
|
||||
this->audio_device_menu->reset_output_option();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2257,6 +2286,9 @@ void WindowScreen::prepare_menu_draws(int view_size_x, int view_size_y) {
|
||||
case INPUT_MENU_TYPE:
|
||||
this->input_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->shared_data->input_data);
|
||||
break;
|
||||
case AUDIO_DEVICE_MENU_TYPE:
|
||||
this->audio_device_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, this->audio_data->get_audio_output_device_data());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2333,6 +2365,9 @@ void WindowScreen::execute_menu_draws() {
|
||||
case INPUT_MENU_TYPE:
|
||||
this->input_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
|
||||
break;
|
||||
case AUDIO_DEVICE_MENU_TYPE:
|
||||
this->audio_device_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
#include "audio_data.hpp"
|
||||
|
||||
int searchAudioDevice(std::string device_name, std::vector<std::string> &audio_devices) {
|
||||
int index = -1;
|
||||
for(int i = 0; i < audio_devices.size(); i++)
|
||||
if(audio_devices[i] == device_name) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
void AudioData::reset() {
|
||||
this->volume = 100;
|
||||
this->mute = false;
|
||||
@@ -7,6 +17,8 @@ void AudioData::reset() {
|
||||
this->output_type = AUDIO_OUTPUT_STEREO;
|
||||
this->restart_request = false;
|
||||
this->text_updated = false;
|
||||
this->output_device.preference_requested = false;
|
||||
this->output_device.preferred = "";
|
||||
}
|
||||
|
||||
void AudioData::change_max_audio_latency(bool is_change_positive) {
|
||||
@@ -77,6 +89,19 @@ bool AudioData::has_text_to_print() {
|
||||
return retval;
|
||||
}
|
||||
|
||||
void AudioData::set_audio_output_device_data(audio_output_device_data new_device_data) {
|
||||
bool had_preference = this->output_device.preference_requested;
|
||||
if(had_preference)
|
||||
this->output_device.preference_requested = new_device_data.preference_requested;
|
||||
this->output_device.preferred = new_device_data.preferred;
|
||||
if(!had_preference)
|
||||
this->output_device.preference_requested = new_device_data.preference_requested;
|
||||
}
|
||||
|
||||
audio_output_device_data AudioData::get_audio_output_device_data() {
|
||||
return this->output_device;
|
||||
}
|
||||
|
||||
std::string AudioData::text_to_print() {
|
||||
return this->text;
|
||||
}
|
||||
@@ -147,6 +172,14 @@ bool AudioData::load_audio_data(std::string key, std::string value) {
|
||||
this->set_audio_output_type(std::stoi(value));
|
||||
return true;
|
||||
}
|
||||
if (key == this->device_request_str) {
|
||||
this->output_device.preference_requested = std::stoi(value);
|
||||
return true;
|
||||
}
|
||||
if (key == this->device_name_str) {
|
||||
this->output_device.preferred = value;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -156,6 +189,8 @@ std::string AudioData::save_audio_data() {
|
||||
out_str += this->volume_str + "=" + std::to_string(this->volume) + "\n";
|
||||
out_str += this->max_audio_latency_str + "=" + std::to_string(this->max_audio_latency) + "\n";
|
||||
out_str += this->output_type_str + "=" + std::to_string(this->output_type) + "\n";
|
||||
out_str += this->device_request_str + "=" + std::to_string(this->output_device.preference_requested) + "\n";
|
||||
out_str += this->device_name_str + "=" + this->output_device.preferred + "\n";
|
||||
return out_str;
|
||||
}
|
||||
|
||||
|
||||
@@ -328,12 +328,25 @@ static void executeSoundRestart(Audio &audio, AudioData* audio_data, bool do_res
|
||||
audio.play();
|
||||
}
|
||||
|
||||
static bool setDefaultAudioDevice(Audio &audio) {
|
||||
bool success = false;
|
||||
std::optional<std::string> default_device = sf::PlaybackDevice::getDefaultDevice();
|
||||
if(default_device) {
|
||||
audio.stop_audio();
|
||||
audio.stop();
|
||||
success = sf::PlaybackDevice::setDevice(default_device.value());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
static void soundCall(AudioData *audio_data, CaptureData* capture_data) {
|
||||
std::int16_t (*out_buf)[MAX_SAMPLES_IN] = new std::int16_t[NUM_CONCURRENT_AUDIO_BUFFERS][MAX_SAMPLES_IN];
|
||||
Audio audio(audio_data);
|
||||
int audio_buf_counter = 0;
|
||||
const bool endianness = is_big_endian();
|
||||
volatile int loaded_samples;
|
||||
audio_output_device_data in_use_audio_output_device_data;
|
||||
std::optional<std::string> curr_device = sf::PlaybackDevice::getDevice();
|
||||
|
||||
while(capture_data->status.running) {
|
||||
if(capture_data->status.connected && capture_data->status.device.has_audio) {
|
||||
@@ -361,14 +374,22 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) {
|
||||
loaded_samples = audio.samples.size();
|
||||
if(audio.getStatus() != sf::SoundStream::Status::Playing) {
|
||||
audio.stop_audio();
|
||||
if(loaded_samples > 0)
|
||||
executeSoundRestart(audio, audio_data, audio.restart);
|
||||
if(loaded_samples > 0) {
|
||||
bool do_restart = audio.restart;
|
||||
executeSoundRestart(audio, audio_data, do_restart);
|
||||
if(do_restart) {
|
||||
in_use_audio_output_device_data.preference_requested = false;
|
||||
curr_device = sf::PlaybackDevice::getDevice();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(loaded_samples > 0) {
|
||||
if(audio.hasTooMuchTimeElapsed()) {
|
||||
audio.stop_audio();
|
||||
executeSoundRestart(audio, audio_data, true);
|
||||
in_use_audio_output_device_data.preference_requested = false;
|
||||
curr_device = sf::PlaybackDevice::getDevice();
|
||||
}
|
||||
}
|
||||
audio.update_volume();
|
||||
@@ -379,6 +400,44 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) {
|
||||
audio.stop();
|
||||
default_sleep();
|
||||
}
|
||||
|
||||
// Code for audio device selection
|
||||
audio_output_device_data new_audio_output_device_data = audio_data->get_audio_output_device_data();
|
||||
if((new_audio_output_device_data.preference_requested != in_use_audio_output_device_data.preference_requested) || (new_audio_output_device_data.preference_requested && (new_audio_output_device_data.preferred != in_use_audio_output_device_data.preferred))) {
|
||||
int index = -1;
|
||||
bool success = false;
|
||||
if(new_audio_output_device_data.preference_requested) {
|
||||
std::vector<std::string> audio_devices = sf::PlaybackDevice::getAvailableDevices();
|
||||
index = searchAudioDevice(new_audio_output_device_data.preferred, audio_devices);
|
||||
if(index != -1) {
|
||||
audio.stop_audio();
|
||||
audio.stop();
|
||||
success = sf::PlaybackDevice::setDevice(audio_devices[index]);
|
||||
}
|
||||
}
|
||||
if(index == -1)
|
||||
success = setDefaultAudioDevice(audio);
|
||||
if(success)
|
||||
curr_device = sf::PlaybackDevice::getDevice();
|
||||
}
|
||||
in_use_audio_output_device_data = new_audio_output_device_data;
|
||||
if(!in_use_audio_output_device_data.preference_requested) {
|
||||
std::optional<std::string> default_device = sf::PlaybackDevice::getDefaultDevice();
|
||||
if(default_device != curr_device) {
|
||||
bool success = setDefaultAudioDevice(audio);
|
||||
if(success)
|
||||
curr_device = sf::PlaybackDevice::getDevice();
|
||||
}
|
||||
}
|
||||
else if(curr_device) {
|
||||
std::vector<std::string> audio_devices = sf::PlaybackDevice::getAvailableDevices();
|
||||
int index = searchAudioDevice(curr_device.value(), audio_devices);
|
||||
if(index == -1) {
|
||||
bool success = setDefaultAudioDevice(audio);
|
||||
if(success)
|
||||
curr_device = sf::PlaybackDevice::getDevice();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
audio.stop_audio();
|
||||
@@ -765,7 +824,7 @@ int main(int argc, char **argv) {
|
||||
std::cout << " even if multiple are present." << std::endl;
|
||||
std::cout << " --failure_close Automatically closes the software if the first connection" << std::endl;
|
||||
std::cout << " doesn't succeed." << std::endl;
|
||||
std::cout << " --failure_close Automatically closes the software on disconnect." << std::endl;
|
||||
std::cout << " --auto_close Automatically closes the software on disconnect." << std::endl;
|
||||
std::cout << " --profile Loads the profile with the specified ID at startup" << std::endl;
|
||||
std::cout << " instead of the default one. When the program closes," << std::endl;
|
||||
std::cout << " the data is also saved to the specified profile." << std::endl;
|
||||
|
||||
Reference in New Issue
Block a user