diff --git a/CMakeLists.txt b/CMakeLists.txt index bc672f4..fadbfd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,7 +132,7 @@ file(MAKE_DIRECTORY ${TOOLS_DATA_DIR}) set(OUTPUT_NAME cc3dsfs) add_executable(CMakeBin2C tools/bin2c.cpp) -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/3dscapture.cpp source/conversions.cpp source/ConnectionMenu.cpp source/OptionSelectionMenu.cpp source/MainMenu.cpp source/VideoMenu.cpp source/CropMenu.cpp source/PARMenu.cpp source/RotationMenu.cpp source/OffsetMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp) +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/3dscapture.cpp source/conversions.cpp source/ConnectionMenu.cpp source/OptionSelectionMenu.cpp source/MainMenu.cpp source/VideoMenu.cpp source/CropMenu.cpp source/PARMenu.cpp source/RotationMenu.cpp source/OffsetMenu.cpp source/AudioMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp) add_dependencies(${OUTPUT_NAME} FTD3XX_BUILD_PROJECT CMakeBin2C) target_link_libraries(${OUTPUT_NAME} PRIVATE sfml-graphics sfml-audio sfml-window sfml-system ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_LIB}) target_link_directories(${OUTPUT_NAME} PRIVATE ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}) diff --git a/include/AudioMenu.hpp b/include/AudioMenu.hpp new file mode 100755 index 0000000..4665880 --- /dev/null +++ b/include/AudioMenu.hpp @@ -0,0 +1,38 @@ +#ifndef __AUDIOMENU_HPP +#define __AUDIOMENU_HPP + +#include "OptionSelectionMenu.hpp" +#include + +#include "TextRectangle.hpp" +#include "sfml_gfx_structs.hpp" +#include "audio_data.hpp" + +enum AudioMenuOutAction{ + AUDIO_MENU_NO_ACTION, + AUDIO_MENU_BACK, + AUDIO_MENU_MUTE, + AUDIO_MENU_VOLUME_DEC, + AUDIO_MENU_VOLUME_INC, + AUDIO_MENU_RESTART, +}; + +class AudioMenu : public OptionSelectionMenu { +public: + AudioMenu(bool font_load_success, sf::Font &text_font); + ~AudioMenu(); + void prepare(float scaling_factor, int view_size_x, int view_size_y, AudioData *audio_data); + void insert_data(); + AudioMenuOutAction selected_index = AudioMenuOutAction::AUDIO_MENU_NO_ACTION; + void reset_output_option(); +protected: + bool is_option_inc_dec(int index); + 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: + int *options_indexes; + int num_enabled_options; +}; +#endif diff --git a/include/ConnectionMenu.hpp b/include/ConnectionMenu.hpp index b1cbc5d..923225e 100755 --- a/include/ConnectionMenu.hpp +++ b/include/ConnectionMenu.hpp @@ -5,15 +5,17 @@ #include "capture_structs.hpp" +#define CONNECTION_MENU_NO_ACTION (-1) + class ConnectionMenu : public OptionSelectionMenu { public: ConnectionMenu(bool font_load_success, sf::Font &text_font); ~ConnectionMenu(); void prepare(float scaling_factor, int view_size_x, int view_size_y); void insert_data(DevicesList *devices_list); - int selected_index = -1; -protected: + int selected_index = CONNECTION_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); diff --git a/include/CropMenu.hpp b/include/CropMenu.hpp index 9ca2fe7..1e1b8b3 100755 --- a/include/CropMenu.hpp +++ b/include/CropMenu.hpp @@ -18,8 +18,8 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, int current_crop); void insert_data(std::vector* possible_crops); int selected_index = CROP_MENU_NO_ACTION; -protected: 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); diff --git a/include/MainMenu.hpp b/include/MainMenu.hpp index 0851a02..72571bc 100755 --- a/include/MainMenu.hpp +++ b/include/MainMenu.hpp @@ -32,8 +32,8 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, bool connected); void insert_data(ScreenType s_type, bool is_fullscreen); MainMenuOutAction selected_index = MainMenuOutAction::MAIN_MENU_NO_ACTION; -protected: 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); diff --git a/include/OffsetMenu.hpp b/include/OffsetMenu.hpp index ecc051b..18496b0 100755 --- a/include/OffsetMenu.hpp +++ b/include/OffsetMenu.hpp @@ -28,9 +28,9 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info); void insert_data(); OffsetMenuOutAction selected_index = OffsetMenuOutAction::OFFSET_MENU_NO_ACTION; + void reset_output_option(); protected: bool is_option_inc_dec(int index); - void reset_output_option(); void set_output_option(int index, int action); int get_num_options(); std::string get_string_option(int index, int action); diff --git a/include/OptionSelectionMenu.hpp b/include/OptionSelectionMenu.hpp index 8729992..d67bb46 100755 --- a/include/OptionSelectionMenu.hpp +++ b/include/OptionSelectionMenu.hpp @@ -22,6 +22,7 @@ public: void draw(float scaling_factor, sf::RenderTarget &window); void reset_data(); std::chrono::time_point last_input_processed_time; + virtual void reset_output_option(); protected: int num_options_per_screen; int elements_start_id; @@ -39,7 +40,6 @@ protected: bool show_title; virtual bool is_option_inc_dec(int index); - virtual void reset_output_option(); virtual void set_output_option(int index, int action); virtual int get_num_options(); virtual std::string get_string_option(int index, int action); diff --git a/include/PARMenu.hpp b/include/PARMenu.hpp index 94efbc5..97e1e53 100755 --- a/include/PARMenu.hpp +++ b/include/PARMenu.hpp @@ -19,8 +19,8 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, int current_crop); void insert_data(std::vector* possible_pars); int selected_index = PAR_MENU_NO_ACTION; -protected: 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); diff --git a/include/RotationMenu.hpp b/include/RotationMenu.hpp index d730ce6..683d60d 100755 --- a/include/RotationMenu.hpp +++ b/include/RotationMenu.hpp @@ -26,9 +26,9 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info); void insert_data(); RotationMenuOutAction selected_index = RotationMenuOutAction::ROTATION_MENU_NO_ACTION; + void reset_output_option(); protected: bool is_option_inc_dec(int index); - void reset_output_option(); void set_output_option(int index, int action); int get_num_options(); std::string get_string_option(int index, int action); diff --git a/include/VideoMenu.hpp b/include/VideoMenu.hpp index dc3ec4e..529b272 100755 --- a/include/VideoMenu.hpp +++ b/include/VideoMenu.hpp @@ -45,9 +45,9 @@ public: void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info); void insert_data(ScreenType s_type, bool is_fullscreen); VideoMenuOutAction selected_index = VideoMenuOutAction::VIDEO_MENU_NO_ACTION; + void reset_output_option(); protected: bool is_option_inc_dec(int index); - void reset_output_option(); void set_output_option(int index, int action); int get_num_options(); std::string get_string_option(int index, int action); diff --git a/include/audio_data.hpp b/include/audio_data.hpp index 1b17efd..edd0104 100755 --- a/include/audio_data.hpp +++ b/include/audio_data.hpp @@ -13,6 +13,7 @@ public: int get_final_volume(); bool has_text_to_print(); std::string text_to_print(); + bool get_mute(); int get_real_volume(); bool load_audio_data(std::string key, std::string value); std::string save_audio_data(); @@ -22,8 +23,10 @@ private: bool mute; bool restart_request = false; bool text_updated; + std::string text; void set_audio_volume(int new_volume); void set_audio_mute(bool new_mute); + void update_text(std::string text); const std::string volume_str = "volume"; const std::string mute_str = "mute"; }; diff --git a/include/frontend.hpp b/include/frontend.hpp index 64f6fb4..de4ecc2 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -19,6 +19,7 @@ #include "PARMenu.hpp" #include "RotationMenu.hpp" #include "OffsetMenu.hpp" +#include "AudioMenu.hpp" #include "display_structs.hpp" class WindowScreen { @@ -88,6 +89,7 @@ private: PARMenu *par_menu; RotationMenu *rotation_menu; OffsetMenu *offset_menu; + AudioMenu *audio_menu; std::vector possible_crops; std::vector possible_pars; @@ -173,6 +175,7 @@ private: void setup_par_menu(bool is_top); void setup_offset_menu(); void setup_rotation_menu(); + void setup_audio_menu(); void update_connection(); }; diff --git a/source/3dscapture.cpp b/source/3dscapture.cpp index 51a98a9..9af78b2 100755 --- a/source/3dscapture.cpp +++ b/source/3dscapture.cpp @@ -14,6 +14,8 @@ #define FIFO_CHANNEL 0 #endif +#define CONNECTION_NO_DEVICE_SELECTED (-1) + static bool get_is_bad_ftd3xx() { #if (defined(_WIN32) || defined(_WIN64)) return false; @@ -73,7 +75,7 @@ static void list_devices(DevicesList &devices_list) { static bool poll_connection_window_screen(WindowScreen *screen, int &chosen_index) { screen->poll(); - if(screen->check_connection_menu_result() != -1) { + if(screen->check_connection_menu_result() != CONNECTION_MENU_NO_ACTION) { chosen_index = screen->check_connection_menu_result(); return true; } @@ -86,7 +88,7 @@ static bool poll_connection_window_screen(WindowScreen *screen, int &chosen_inde static int choose_device(DevicesList *devices_list, FrontendData* frontend_data) { if(devices_list->numValidDevices == 1) return 0; - int chosen_index = -1; + int chosen_index = CONNECTION_NO_DEVICE_SELECTED; frontend_data->top_screen->setup_connection_menu(devices_list); frontend_data->bot_screen->setup_connection_menu(devices_list); frontend_data->joint_screen->setup_connection_menu(devices_list); @@ -144,7 +146,7 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten } int chosen_device = choose_device(&devices_list, frontend_data); - if(chosen_device == -1) { + if(chosen_device == CONNECTION_NO_DEVICE_SELECTED) { if(print_failed) { capture_data->status.error_text = "No device was selected"; capture_data->status.new_error_text = true; diff --git a/source/AudioMenu.cpp b/source/AudioMenu.cpp new file mode 100755 index 0000000..4136aea --- /dev/null +++ b/source/AudioMenu.cpp @@ -0,0 +1,133 @@ +#include "AudioMenu.hpp" + +#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0])) + +struct AudioMenuOptionInfo { + const std::string base_name; + const std::string false_name; + const bool is_inc; + const std::string dec_str; + const std::string inc_str; + const AudioMenuOutAction inc_out_action; + const AudioMenuOutAction out_action; +}; + +static const AudioMenuOptionInfo audio_volume_option = { +.base_name = "Volume", .false_name = "", +.is_inc = true, .dec_str = "-", .inc_str = "+", .inc_out_action = AUDIO_MENU_VOLUME_INC, +.out_action = AUDIO_MENU_VOLUME_DEC}; + +static const AudioMenuOptionInfo audio_mute_option = { +.base_name = "Unmute Audio", .false_name = "Mute Audio", +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = AUDIO_MENU_NO_ACTION, +.out_action = AUDIO_MENU_MUTE}; + +static const AudioMenuOptionInfo audio_restart_option = { +.base_name = "Restart Audio", .false_name = "", +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = AUDIO_MENU_NO_ACTION, +.out_action = AUDIO_MENU_RESTART}; + +static const AudioMenuOptionInfo* pollable_options[] = { +&audio_volume_option, +&audio_mute_option, +&audio_restart_option, +}; + +AudioMenu::AudioMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){ + this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS]; + this->initialize(font_load_success, text_font); + this->num_enabled_options = 0; +} + +AudioMenu::~AudioMenu() { + delete []this->options_indexes; +} + +void AudioMenu::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 Settings"; + this->show_back_x = true; + this->show_x = false; + this->show_title = true; +} + +void AudioMenu::insert_data() { + this->num_enabled_options = 0; + for(int i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) { + this->options_indexes[this->num_enabled_options] = i; + this->num_enabled_options++; + } + this->prepare_options(); +} + +void AudioMenu::reset_output_option() { + this->selected_index = AudioMenuOutAction::AUDIO_MENU_NO_ACTION; +} + +void AudioMenu::set_output_option(int index, int action) { + if(index == BACK_X_OUTPUT_OPTION) + this->selected_index = AUDIO_MENU_BACK; + else if((action == INC_ACTION) && this->is_option_inc_dec(index)) + this->selected_index = pollable_options[this->options_indexes[index]]->inc_out_action; + else + this->selected_index = pollable_options[this->options_indexes[index]]->out_action; +} + +int AudioMenu::get_num_options() { + return this->num_enabled_options; +} + +std::string AudioMenu::get_string_option(int index, int action) { + if((action == INC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->inc_str; + if((action == DEC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->dec_str; + return pollable_options[this->options_indexes[index]]->base_name; +} + +bool AudioMenu::is_option_inc_dec(int index) { + return pollable_options[this->options_indexes[index]]->is_inc; +} + +static std::string setTextOptionInt(int option_index, int value) { + return pollable_options[option_index]->base_name + ": " + std::to_string(value); +} + +static std::string setTextOptionBool(int option_index, bool value) { + if(value) + return pollable_options[option_index]->base_name; + return pollable_options[option_index]->false_name; +} + +void AudioMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, AudioData *audio_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 option_index = this->options_indexes[start + i]; + switch(pollable_options[option_index]->out_action) { + case AUDIO_MENU_VOLUME_DEC: + this->labels[index]->setText(setTextOptionInt(option_index, audio_data->get_real_volume())); + break; + case AUDIO_MENU_MUTE: + this->labels[index]->setText(setTextOptionBool(option_index, audio_data->get_mute())); + break; + default: + break; + } + } + + this->base_prepare(menu_scaling_factor, view_size_x, view_size_y); +} diff --git a/source/WindowScreen.cpp b/source/WindowScreen.cpp index 150c80e..c13ddeb 100755 --- a/source/WindowScreen.cpp +++ b/source/WindowScreen.cpp @@ -27,6 +27,7 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp this->par_menu = new PARMenu(this->font_load_success, this->text_font); this->offset_menu = new OffsetMenu(this->font_load_success, this->text_font); this->rotation_menu = new RotationMenu(this->font_load_success, this->text_font); + this->audio_menu = new AudioMenu(this->font_load_success, this->text_font); this->in_tex.create(IN_VIDEO_WIDTH, IN_VIDEO_HEIGHT); this->m_in_rect_top.setTexture(&this->in_tex); this->m_in_rect_bot.setTexture(&this->in_tex); @@ -59,6 +60,7 @@ WindowScreen::~WindowScreen() { delete this->par_menu; delete this->offset_menu; delete this->rotation_menu; + delete this->audio_menu; } void WindowScreen::build() { @@ -389,6 +391,14 @@ void WindowScreen::setup_rotation_menu() { } } +void WindowScreen::setup_audio_menu() { + if(this->curr_menu != AUDIO_MENU_TYPE) { + this->curr_menu = AUDIO_MENU_TYPE; + this->audio_menu->reset_data(); + this->audio_menu->insert_data(); + } +} + bool WindowScreen::no_menu_poll(SFEvent &event_data) { bool consumed = true; switch(event_data.type) { @@ -545,7 +555,6 @@ bool WindowScreen::main_poll(SFEvent &event_data) { case 'n': audio_data->request_audio_restart(); - this->print_notification("Restarting audio..."); break; default: @@ -627,7 +636,7 @@ void WindowScreen::poll() { break; case CONNECT_MENU_TYPE: if(this->connection_menu->poll(event_data)) { - if(this->check_connection_menu_result() != -1) + if(this->check_connection_menu_result() != CONNECTION_MENU_NO_ACTION) return; continue; } @@ -654,10 +663,13 @@ void WindowScreen::poll() { case MAIN_MENU_VIDEO_SETTINGS: this->setup_video_menu(); return; + case MAIN_MENU_AUDIO_SETTINGS: + this->setup_audio_menu(); + return; default: break; } - this->main_menu->selected_index = MAIN_MENU_NO_ACTION; + this->main_menu->reset_output_option(); continue; } break; @@ -742,7 +754,7 @@ void WindowScreen::poll() { default: break; } - this->video_menu->selected_index = VIDEO_MENU_NO_ACTION; + this->video_menu->reset_output_option(); continue; } case CROP_MENU_TYPE: @@ -757,7 +769,7 @@ void WindowScreen::poll() { this->crop_value_change(this->crop_menu->selected_index); break; } - this->crop_menu->selected_index = CROP_MENU_NO_ACTION; + this->crop_menu->reset_output_option(); continue; } break; @@ -773,7 +785,7 @@ void WindowScreen::poll() { this->par_value_change(this->par_menu->selected_index, true); break; } - this->par_menu->selected_index = PAR_MENU_NO_ACTION; + this->par_menu->reset_output_option(); continue; } break; @@ -789,7 +801,7 @@ void WindowScreen::poll() { this->par_value_change(this->par_menu->selected_index, false); break; } - this->par_menu->selected_index = PAR_MENU_NO_ACTION; + this->par_menu->reset_output_option(); continue; } break; @@ -824,7 +836,7 @@ void WindowScreen::poll() { default: break; } - this->rotation_menu->selected_index = ROTATION_MENU_NO_ACTION; + this->rotation_menu->reset_output_option(); continue; } break; @@ -863,7 +875,34 @@ void WindowScreen::poll() { default: break; } - this->offset_menu->selected_index = OFFSET_MENU_NO_ACTION; + this->offset_menu->reset_output_option(); + continue; + } + break; + case AUDIO_MENU_TYPE: + if(this->audio_menu->poll(event_data)) { + switch(this->audio_menu->selected_index) { + case AUDIO_MENU_BACK: + this->setup_main_menu(); + return; + case AUDIO_MENU_NO_ACTION: + break; + case AUDIO_MENU_VOLUME_DEC: + this->audio_data->change_audio_volume(false); + break; + case AUDIO_MENU_VOLUME_INC: + this->audio_data->change_audio_volume(true); + break; + case AUDIO_MENU_MUTE: + this->audio_data->change_audio_mute(); + break; + case AUDIO_MENU_RESTART: + this->audio_data->request_audio_restart(); + break; + default: + break; + } + this->audio_menu->reset_output_option(); continue; } break; @@ -977,6 +1016,9 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) { case OFFSET_MENU_TYPE: this->offset_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info); break; + case AUDIO_MENU_TYPE: + this->audio_menu->prepare(this->loaded_info.menu_scaling_factor, view_size_x, view_size_y, this->audio_data); + break; default: break; } @@ -1304,6 +1346,9 @@ void WindowScreen::display_data_to_window(bool actually_draw, bool is_debug) { case OFFSET_MENU_TYPE: this->offset_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win); break; + case AUDIO_MENU_TYPE: + this->audio_menu->draw(this->loaded_info.menu_scaling_factor, this->m_win); + break; default: break; } diff --git a/source/audio_data.cpp b/source/audio_data.cpp index 839bc44..a3252aa 100755 --- a/source/audio_data.cpp +++ b/source/audio_data.cpp @@ -16,16 +16,20 @@ void AudioData::change_audio_volume(bool is_change_positive) { this->set_audio_volume(this->volume + volume_change); this->set_audio_mute(false); if((this->volume != initial_audio_volume) || (initial_audio_mute)) - this->text_updated = true; + this->update_text("Volume: " + std::to_string(this->get_final_volume()) + "%"); } void AudioData::change_audio_mute() { this->set_audio_mute(!this->mute); - this->text_updated = true; + if(this->mute) + this->update_text("Audio muted"); + else + this->update_text("Volume: " + std::to_string(this->get_final_volume()) + "%"); } void AudioData::request_audio_restart() { this->restart_request = true; + this->update_text("Restarting audio..."); } bool AudioData::check_audio_restart_request() { @@ -35,6 +39,11 @@ bool AudioData::check_audio_restart_request() { return retval; } +void AudioData::update_text(std::string text) { + this->text = text; + this->text_updated = true; +} + bool AudioData::has_text_to_print() { bool retval = this->text_updated; if(retval) @@ -43,9 +52,7 @@ bool AudioData::has_text_to_print() { } std::string AudioData::text_to_print() { - if(this->mute) - return "Audio muted"; - return "Volume: " + std::to_string(this->get_final_volume()) + "%"; + return this->text; } int AudioData::get_final_volume() { @@ -59,6 +66,19 @@ int AudioData::get_final_volume() { return read_volume; } +int AudioData::get_real_volume() { + int read_volume = this->volume; + if(read_volume < 0) + read_volume = 0; + if(read_volume > 100) + read_volume = 100; + return read_volume; +} + +bool AudioData::get_mute() { + return this->mute; +} + bool AudioData::load_audio_data(std::string key, std::string value) { if (key == this->mute_str) { this->set_audio_mute(std::stoi(value));