diff --git a/CMakeLists.txt b/CMakeLists.txt index 146d241..e418da5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,7 +84,7 @@ set(OUTPUT_NAME cc3dsfs) add_custom_target(CMakeFTD3XX) add_custom_target(CMakeBin2C) -add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/3dscapture.cpp source/conversions.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 ${TOOLS_DATA_DIR}/font_ttf.cpp) add_dependencies(${OUTPUT_NAME} CMakeFTD3XX) if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") target_link_libraries(${OUTPUT_NAME} PRIVATE sfml-graphics sfml-audio sfml-window sfml-system FTD3XX) diff --git a/include/audio.hpp b/include/audio.hpp index 7467cc0..7c7158f 100755 --- a/include/audio.hpp +++ b/include/audio.hpp @@ -3,16 +3,12 @@ #include #include +#include "audio_data.hpp" #include "utils.hpp" #include "audio.hpp" #include "3dscapture.hpp" #include "hw_defs.hpp" -struct AudioData { - int volume; - bool mute; -}; - struct Sample { Sample(sf::Int16 *bytes, std::size_t size, float time); @@ -27,14 +23,14 @@ public: std::queue samples; ConsumerMutex samples_wait; - Audio(); - void update_volume(int volume, bool mute); + Audio(AudioData *audio_data); + void update_volume(); void start_audio(); void stop_audio(); private: - int loaded_volume = -1; - bool loaded_mute = false; + AudioData *audio_data; + int final_volume = -1; bool terminate; int num_consecutive_fast_seek; sf::Int16 buffer[MAX_SAMPLES_IN]; diff --git a/include/audio_data.hpp b/include/audio_data.hpp new file mode 100755 index 0000000..bb348bd --- /dev/null +++ b/include/audio_data.hpp @@ -0,0 +1,28 @@ +#ifndef __AUDIO_DATA_HPP +#define __AUDIO_DATA_HPP + +#include + +class AudioData { +public: + void reset(); + void change_audio_volume(bool is_change_positive); + void change_audio_mute(); + int get_final_volume(); + bool has_text_to_print(); + std::string text_to_print(); + int get_real_volume(); + bool load_audio_data(std::string key, std::string value); + std::string save_audio_data(); + +private: + int volume; + bool mute; + bool text_updated; + void set_audio_volume(int new_volume); + void set_audio_mute(bool new_mute); + const std::string volume_str = "volume"; + const std::string mute_str = "mute"; +}; + +#endif diff --git a/include/frontend.hpp b/include/frontend.hpp index dbf71ce..884aa21 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -4,8 +4,11 @@ #include #include +#include #include "utils.hpp" -#include "audio.hpp" +#include "audio_data.hpp" +#include "3dscapture.hpp" +#include "hw_defs.hpp" enum Crop { DEFAULT_3DS, SPECIAL_DS, SCALED_DS, NATIVE_DS, SCALED_GBA, NATIVE_GBA, SCALED_GB, NATIVE_GB, NATIVE_SNES, NATIVE_NES, CROP_END }; enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END }; @@ -53,7 +56,7 @@ struct out_rect_data { }; void reset_screen_info(ScreenInfo &info); -void load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info); +bool load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info); std::string save_screen_info(std::string base, const ScreenInfo &info); enum TextKind {TEXT_KIND_NORMAL, TEXT_KIND_SELECTED, TEXT_KIND_SUCCESS, TEXT_KIND_WARNING, TEXT_KIND_ERROR}; diff --git a/source/WindowScreen.cpp b/source/WindowScreen.cpp index 079c448..fa5df7f 100755 --- a/source/WindowScreen.cpp +++ b/source/WindowScreen.cpp @@ -84,6 +84,7 @@ void WindowScreen::reload() { } void WindowScreen::poll() { + float old_scaling = 0.0; this->poll_window(); while(!events_queue.empty()) { SFEvent event_data = events_queue.front(); @@ -124,6 +125,7 @@ void WindowScreen::poll() { case 'b': this->m_info.is_blurred = !this->m_info.is_blurred; this->future_operations.call_blur = true; + this->print_notification_on_off("Blur", this->m_info.is_blurred); break; case 'v': @@ -137,15 +139,25 @@ void WindowScreen::poll() { break; case '-': + if(this->m_info.is_fullscreen) + break; + old_scaling = this->m_info.scaling; this->m_info.scaling -= 0.5; if (this->m_info.scaling < 1.25) this->m_info.scaling = 1.0; + if(old_scaling != this->m_info.scaling) + this->print_notification("Scaling: " + std::to_string(this->m_info.scaling)); break; case '0': + if(this->m_info.is_fullscreen) + break; + old_scaling = this->m_info.scaling; this->m_info.scaling += 0.5; if (this->m_info.scaling > 44.75) this->m_info.scaling = 45.0; + if(old_scaling != this->m_info.scaling) + this->print_notification("Scaling: " + std::to_string(this->m_info.scaling)); break; case 'o': @@ -237,21 +249,15 @@ void WindowScreen::poll() { break; case 'm': - audio_data->mute = !audio_data->mute; + audio_data->change_audio_mute(); break; case ',': - audio_data->mute = false; - audio_data->volume -= 5; - if(audio_data->volume < 0) - audio_data->volume = 0; + audio_data->change_audio_volume(false); break; case '.': - audio_data->mute = false; - audio_data->volume += 5; - if(audio_data->volume > 100) - audio_data->volume = 100; + audio_data->change_audio_volume(true); break; default: diff --git a/source/audio.cpp b/source/audio.cpp index 9a24469..c73f1ea 100755 --- a/source/audio.cpp +++ b/source/audio.cpp @@ -14,7 +14,8 @@ Sample::Sample(sf::Int16 *bytes, std::size_t size, float time) : bytes(bytes), s //============================================================================ -Audio::Audio() { +Audio::Audio(AudioData *audio_data) { + this->audio_data = audio_data; sf::SoundStream::initialize(AUDIO_CHANNELS, SAMPLE_RATE); #if (SFML_VERSION_MAJOR > 2) || ((SFML_VERSION_MAJOR == 2) && (SFML_VERSION_MINOR >= 6)) // Since we receive data every 16.6 ms, this is useless, @@ -22,30 +23,15 @@ Audio::Audio() { //sf::SoundStream::setProcessingInterval(sf::Time::Zero); #endif start_audio(); + setVolume(0); + this->final_volume = 0; } -void Audio::update_volume(int volume, bool mute) { - if(mute && (mute == loaded_mute)) { - return; - } - - if(volume < 0) - volume = 0; - if(volume > 100) - volume = 100; - - if(mute != loaded_mute) { - loaded_mute = mute; - loaded_volume = volume; - } - else if(volume != loaded_volume) { - loaded_mute = mute; - loaded_volume = volume; - } - else { - return; - } - setVolume(mute ? 0 : volume); +void Audio::update_volume() { + int new_final_volume = this->audio_data->get_final_volume(); + if(this->final_volume != new_final_volume) + setVolume(new_final_volume); + this->final_volume = new_final_volume; } void Audio::start_audio() { diff --git a/source/audio_data.cpp b/source/audio_data.cpp new file mode 100755 index 0000000..25c3b30 --- /dev/null +++ b/source/audio_data.cpp @@ -0,0 +1,78 @@ +#include "audio_data.hpp" + +void AudioData::reset() { + this->volume = 50; + this->mute = false; + this->text_updated = false; +} + +void AudioData::change_audio_volume(bool is_change_positive) { + bool initial_audio_mute = this->mute; + int initial_audio_volume = this->volume; + int volume_change = 5; + if(!is_change_positive) + volume_change *= -1; + 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; +} + +void AudioData::change_audio_mute() { + this->set_audio_mute(!this->mute); + this->text_updated = true; +} + +bool AudioData::has_text_to_print() { + bool retval = this->text_updated; + this->text_updated = false; + return retval; +} + +std::string AudioData::text_to_print() { + if(this->mute) + return "Audio muted"; + return "Volume: " + std::to_string(this->get_final_volume()) + "%"; +} + +int AudioData::get_final_volume() { + if(this->mute) + return 0; + int read_volume = this->volume; + if(read_volume < 0) + read_volume = 0; + if(read_volume > 100) + read_volume = 100; + return read_volume; +} + +bool AudioData::load_audio_data(std::string key, std::string value) { + if (key == this->mute_str) { + this->set_audio_mute(std::stoi(value)); + return true; + } + if (key == this->volume_str) { + this->set_audio_volume(std::stoi(value)); + return true; + } + return false; +} + +std::string AudioData::save_audio_data() { + std::string out_str = ""; + out_str += this->mute_str + "=" + std::to_string(this->mute) + "\n"; + out_str += this->volume_str + "=" + std::to_string(this->volume) + "\n"; + return out_str; +} + +void AudioData::set_audio_volume(int new_volume) { + if(new_volume < 0) + new_volume = 0; + if(new_volume > 100) + new_volume = 100; + this->volume = new_volume; +} + +void AudioData::set_audio_mute(bool new_mute) { + this->mute = new_mute; +} diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 82c80b3..1e3fa8b 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -39,7 +39,8 @@ struct OutTextData { }; void ConsoleOutText(std::string full_text) { - std::cout << "[" << NAME << "] " << full_text << std::endl; + if(full_text != "") + std::cout << "[" << NAME << "] " << full_text << std::endl; } void UpdateOutText(OutTextData &out_text_data, std::string full_text, std::string small_text, TextKind kind) { @@ -81,31 +82,23 @@ bool load(const std::string path, const std::string name, ScreenInfo &top_info, if (std::getline(kvp, value)) { - load_screen_info(key, value, "bot_", bottom_info); - load_screen_info(key, value, "joint_", joint_info); - load_screen_info(key, value, "top_", top_info); - - if(bottom_info.crop_kind != Crop::NATIVE_DS) - bottom_info.crop_kind = Crop::DEFAULT_3DS; - if (key == "mute") { - audio_data->mute = std::stoi(value); + if(load_screen_info(key, value, "bot_", bottom_info)) { + if(bottom_info.crop_kind != Crop::NATIVE_DS) + bottom_info.crop_kind = Crop::DEFAULT_3DS; continue; } + if(load_screen_info(key, value, "joint_", joint_info)) + continue; + if(load_screen_info(key, value, "top_", top_info)) + continue; if (key == "split") { display_data.split = std::stoi(value); continue; } - if (key == "volume") { - int pre_loaded_volume = std::stoi(value); - if(pre_loaded_volume < 0) - pre_loaded_volume = 0; - if(pre_loaded_volume > 100) - pre_loaded_volume = 100; - audio_data->volume = pre_loaded_volume; + if(audio_data->load_audio_data(key, value)) continue; - } } } } @@ -129,21 +122,18 @@ bool save(const std::string path, const std::string name, const ScreenInfo &top_ file << save_screen_info("bot_", bottom_info); file << save_screen_info("joint_", joint_info); file << save_screen_info("top_", top_info); - file << "mute=" << audio_data->mute << std::endl; file << "split=" << display_data.split << std::endl; - file << "volume=" << audio_data->volume << std::endl; + file << audio_data->save_audio_data(); file.close(); return true; } void soundCall(AudioData *audio_data, CaptureData* capture_data) { - Audio audio; + Audio audio(audio_data); sf::Int16 out_buf[NUM_CONCURRENT_AUDIO_BUFFERS][MAX_SAMPLES_IN]; int curr_out, prev_out = NUM_CONCURRENT_DATA_BUFFERS - 1, audio_buf_counter = 0; const bool endianness = is_big_endian(); - - audio.update_volume(0, true); volatile int loaded_samples; while (capture_data->running) { @@ -176,14 +166,14 @@ void soundCall(AudioData *audio_data, CaptureData* capture_data) { if(audio.restart) { audio.stop(); audio.~Audio(); - ::new(&audio) Audio(); + ::new(&audio) Audio(audio_data); } audio.start_audio(); audio.play(); } } else { - audio.update_volume(audio_data->volume, audio_data->mute); + audio.update_volume(); } } else { @@ -340,6 +330,10 @@ void mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data) { } } + if(audio_data->has_text_to_print()) { + UpdateOutText(out_text_data, "", audio_data->text_to_print(), TEXT_KIND_NORMAL); + } + if(capture_data->new_error_text) { UpdateOutText(out_text_data, capture_data->error_text, capture_data->error_text, TEXT_KIND_ERROR); capture_data->new_error_text = false; @@ -381,9 +375,8 @@ int main(int argc, char **argv) { XInitThreads(); #endif AudioData audio_data; + audio_data.reset(); CaptureData* capture_data = new CaptureData; - audio_data.volume = 50; - audio_data.mute = false; capture_data->connected = connect(true, capture_data); std::thread capture_thread(captureCall, capture_data); diff --git a/source/frontend.cpp b/source/frontend.cpp index 93c7f20..e86d6f7 100755 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -27,14 +27,14 @@ void reset_screen_info(ScreenInfo &info) { info.bfi_divider = 2.0; } -void load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info) { +bool load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info) { if(key == (base + "blur")) { info.is_blurred = std::stoi(value); - return; + return true; } if(key == (base + "crop")) { info.crop_kind = static_cast(std::stoi(value) % Crop::CROP_END); - return; + return true; } if(key == (base + "scale")) { info.scaling = std::stod(value); @@ -42,70 +42,71 @@ void load_screen_info(std::string key, std::string value, std::string base, Scre info.scaling = 1.0; if(info.scaling > 44.75) info.scaling = 45.0; - return; + return true; } if(key == (base + "fullscreen")) { info.is_fullscreen = std::stoi(value); - return; + return true; } if(key == (base + "bot_pos")) { info.bottom_pos = static_cast(std::stoi(value) % BottomRelativePosition::BOT_REL_POS_END); - return; + return true; } if(key == (base + "sub_off_algo")) { info.subscreen_offset_algorithm = static_cast(std::stoi(value) % OffsetAlgorithm::OFF_ALGO_END); - return; + return true; } if(key == (base + "sub_att_off_algo")) { info.subscreen_attached_offset_algorithm = static_cast(std::stoi(value) % OffsetAlgorithm::OFF_ALGO_END); - return; + return true; } if(key == (base + "off_algo_x")) { info.total_offset_algorithm_x = static_cast(std::stoi(value) % OffsetAlgorithm::OFF_ALGO_END); - return; + return true; } if(key == (base + "off_algo_y")) { info.total_offset_algorithm_y = static_cast(std::stoi(value) % OffsetAlgorithm::OFF_ALGO_END); - return; + return true; } if(key == (base + "top_rot")) { info.top_rotation = std::stoi(value); info.top_rotation %= 360; info.top_rotation += (info.top_rotation < 0) ? 360 : 0; - return; + return true; } if(key == (base + "bot_rot")) { info.bot_rotation = std::stoi(value); info.bot_rotation %= 360; info.bot_rotation += (info.bot_rotation < 0) ? 360 : 0; - return; + return true; } if(key == (base + "vsync")) { info.v_sync_enabled = std::stoi(value); - return; + return true; } if(key == (base + "async")) { info.async = std::stoi(value); - return; + return true; } if(key == (base + "top_scaling")) { info.top_scaling = std::stoi(value); - return; + return true; } if(key == (base + "bot_scaling")) { info.bot_scaling = std::stoi(value); - return; + return true; } if(key == (base + "bfi")) { info.bfi = std::stoi(value); - return; + return true; } if(key == (base + "bfi_divider")) { info.bfi_divider = std::stod(value); if(info.bfi_divider < 1.0) info.bfi_divider = 1.0; - return; + return true; } + return false; } std::string save_screen_info(std::string base, const ScreenInfo &info) {