diff --git a/firmware/application/apps/ui_fileman.hpp b/firmware/application/apps/ui_fileman.hpp index a08334c1..e933702f 100644 --- a/firmware/application/apps/ui_fileman.hpp +++ b/firmware/application/apps/ui_fileman.hpp @@ -77,7 +77,8 @@ class FileManBaseView : public View { {u".C8", &bitmap_icon_file_iq, ui::Color::dark_cyan()}, {u".C16", &bitmap_icon_file_iq, ui::Color::dark_cyan()}, {u".WAV", &bitmap_icon_file_wav, ui::Color::dark_magenta()}, - {u"", &bitmap_icon_file, ui::Color::light_grey()} // NB: Must be last. + {u".PPL", &bitmap_icon_file_iq, ui::Color::white()}, // PPL is the file extension for playlist app + {u"", &bitmap_icon_file, ui::Color::light_grey()} // NB: Must be last. }; std::filesystem::path get_selected_full_path() const; diff --git a/firmware/application/apps/ui_flash_utility.hpp b/firmware/application/apps/ui_flash_utility.hpp index 9ea96c0b..201290ae 100644 --- a/firmware/application/apps/ui_flash_utility.hpp +++ b/firmware/application/apps/ui_flash_utility.hpp @@ -40,7 +40,7 @@ class FlashUtilityView : public View { void focus() override; - std::string title() const override { return "Flash Utility"; }; + std::string title() const override { return "FlashUtility"; }; // Removed the space because the title and speaker icon overlapped. private: NavigationView& nav_; diff --git a/firmware/application/apps/ui_playlist.cpp b/firmware/application/apps/ui_playlist.cpp index b68ecf0a..4b898bea 100644 --- a/firmware/application/apps/ui_playlist.cpp +++ b/firmware/application/apps/ui_playlist.cpp @@ -31,6 +31,7 @@ #include "portapack.hpp" #include "portapack_persistent_memory.hpp" #include +#include using namespace portapack; @@ -53,11 +54,13 @@ void PlaylistView::load_file(std::filesystem::path playlist_path) { if ((int)one_char[0] >= ' ') { line += one_char[0]; } else if (one_char[0] == '\n') { + total_tracks++; txtline_process(line); line.clear(); } } if (line.length() > 0) { + total_tracks++; txtline_process(line); } } @@ -91,8 +94,10 @@ void PlaylistView::on_file_changed(std::filesystem::path new_file_path, rf::Freq File data_file; // Get file size auto data_open_error = data_file.open("/" + new_file_path.string()); - if (data_open_error.is_valid()) { - file_error(); + if (!data_open_error.is_valid()) { + track_number++; + } else if (data_open_error.is_valid()) { + file_error("C16 file\n" + new_file_path.string() + "\nread error."); return; } @@ -109,6 +114,7 @@ void PlaylistView::on_file_changed(std::filesystem::path new_file_path, rf::Freq progressbar.set_max(file_size); text_filename.set(file_path.filename().string().substr(0, 12)); text_duration.set(to_string_time_ms(duration)); + // text_track.set(std::to_string(track_number) + "/" + std::to_string(total_tracks)); button_play.focus(); } @@ -121,8 +127,8 @@ void PlaylistView::focus() { button_open.focus(); } -void PlaylistView::file_error() { - nav_.display_modal("Error", "File " + file_path.string() + " read error. " + file_path.string()); +void PlaylistView::file_error(std::string error_message) { + nav_.display_modal("Error", "Error for \n" + file_path.string() + "\n" + error_message); } bool PlaylistView::is_active() const { @@ -136,7 +142,16 @@ bool PlaylistView::loop() const { void PlaylistView::toggle() { if (is_active()) { stop(false); + total_tracks = 0; + track_number = 0; + playlist_db.clear(); + playlist_masterdb.clear(); } else { + total_tracks = 0; + track_number = 0; + playlist_db.clear(); + playlist_masterdb.clear(); + load_file(now_play_list_file); start(); } } @@ -158,7 +173,7 @@ void PlaylistView::start() { auto p = std::make_unique(); auto open_error = p->open(file_path); if (open_error.is_valid()) { - file_error(); + file_error("illegal grammar(176)"); return; // Fixes TX bug if there's a file error } else { reader = std::move(p); @@ -198,17 +213,41 @@ void PlaylistView::stop(const bool do_loop) { if (is_active()) { replay_thread.reset(); } - if (do_loop) { - if (playlist_db.size() > 0) { - start(); + + // TODO: the logic here could be more beautiful but maybe they are all same for compiler anyway.... + // Notes of the logic here in case if it needed to be changed in the future: + // 1. check_loop.value() is for the LOOP checkbox + // 2. do_loop is a part of the replay thread, not a user - control thing. + // 3. when (total_tracks != track_number) is true, it means that the current track is not the last track. + // Thus, (do_loop && (total_tracks != track_number)) is for the case when the start() func were called with true AND not the last track. + // Which means it do loop until the last track. + + if (check_loop.value()) { + if (do_loop) { + if (playlist_db.size() > 0) { + start(); + } else { + playlist_db = playlist_masterdb; + start(); + } } else { - playlist_db = playlist_masterdb; - start(); + radio::set_antenna_bias(false); // Turn off Bias Tee + radio::disable(); + button_play.set_bitmap(&bitmap_play); + } + } else if (!check_loop.value()) { + if (do_loop && (total_tracks != track_number)) { + if (playlist_db.size() > 0) { + start(); + } else { + playlist_db = playlist_masterdb; + start(); + } + } else { + radio::set_antenna_bias(false); // Turn off Bias Tee + radio::disable(); + button_play.set_bitmap(&bitmap_play); } - } else { - radio::set_antenna_bias(false); // Turn off Bias Tee - radio::disable(); - button_play.set_bitmap(&bitmap_play); } ready_signal = false; @@ -219,7 +258,7 @@ void PlaylistView::handle_replay_thread_done(const uint32_t return_code) { stop(true); } else if (return_code == ReplayThread::READ_ERROR) { stop(false); - file_error(); + file_error("Illegal grammar(255)"); } progressbar.set_value(0); @@ -240,6 +279,8 @@ PlaylistView::PlaylistView( &tx_view, // this handles now the previous rfgain, rfamp &check_loop, &button_play, + // &text_track, + // TODO: add track number &waterfall, }); @@ -264,8 +305,9 @@ PlaylistView::PlaylistView( }; button_open.on_select = [this, &nav](Button&) { - auto open_view = nav.push(".TXT"); + auto open_view = nav.push(".PPL"); open_view->on_changed = [this](std::filesystem::path new_file_path) { + now_play_list_file = new_file_path; load_file(new_file_path); }; }; diff --git a/firmware/application/apps/ui_playlist.hpp b/firmware/application/apps/ui_playlist.hpp index 7efca2c9..84f7fbd1 100644 --- a/firmware/application/apps/ui_playlist.hpp +++ b/firmware/application/apps/ui_playlist.hpp @@ -82,11 +82,14 @@ class PlaylistView : public View { bool loop() const; void set_ready(); void handle_replay_thread_done(const uint32_t return_code); - void file_error(); + void file_error(std::string error_message); std::filesystem::path file_path{}; std::unique_ptr replay_thread{}; bool ready_signal{false}; + int track_number{0}; + int total_tracks{0}; + std::filesystem::path now_play_list_file{}; Button button_open{ {0 * 8, 0 * 16, 10 * 8, 2 * 16}, @@ -125,6 +128,10 @@ class PlaylistView : public View { &bitmap_play, Color::green(), Color::black()}; + // TODO: add track number + // Text text_track{ + // {18 * 8, 1 * 16, 12 * 8, 16}, + // "0/0"}; spectrum::WaterfallWidget waterfall{}; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index 09b30887..f0feaf63 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -22,7 +22,7 @@ #include "ui_navigation.hpp" -//#include "modules.h" +// #include "modules.h" #include "portapack.hpp" #include "event_m0.hpp" @@ -46,13 +46,13 @@ #include "ui_fileman.hpp" #include "ui_freqman.hpp" #include "ui_jammer.hpp" -//#include "ui_keyfob.hpp" +// #include "ui_keyfob.hpp" #include "ui_lcr.hpp" #include "ui_mictx.hpp" #include "ui_morse.hpp" -//#include "ui_numbers.hpp" -//#include "ui_nuoptix.hpp" -//#include "ui_playdead.hpp" +// #include "ui_numbers.hpp" +// #include "ui_nuoptix.hpp" +// #include "ui_playdead.hpp" #include "ui_pocsag_tx.hpp" #include "ui_rds.hpp" #include "ui_remote.hpp" @@ -65,7 +65,7 @@ #include "ui_siggen.hpp" #include "ui_sonde.hpp" #include "ui_sstvtx.hpp" -//#include "ui_test.hpp" +// #include "ui_test.hpp" #include "ui_text_editor.hpp" #include "ui_tone_search.hpp" #include "ui_touchtunes.hpp" @@ -76,7 +76,7 @@ #include "ui_sd_over_usb.hpp" #include "ui_spectrum_painter.hpp" -//#include "acars_app.hpp" +// #include "acars_app.hpp" #include "ais_app.hpp" #include "analog_audio_app.hpp" #include "analog_tv_app.hpp" @@ -563,7 +563,7 @@ TransmittersMenuView::TransmittersMenuView(NavigationView& nav) { {"SSTV", ui::Color::green(), &bitmap_icon_sstv, [&nav]() { nav.push(); }}, {"TEDI/LCR", ui::Color::yellow(), &bitmap_icon_lcr, [&nav]() { nav.push(); }}, {"TouchTune", ui::Color::yellow(), &bitmap_icon_remote, [&nav]() { nav.push(); }}, - {"Playlist", ui::Color::yellow(), &bitmap_icon_remote, [&nav]() { nav.push(); }}, + {"Playlist", ui::Color::green(), &bitmap_icon_scanner, [&nav]() { nav.push(); }}, {"S.Painter", ui::Color::orange(), &bitmap_icon_morse, [&nav]() { nav.push(); }}, //{ "Remote", ui::Color::dark_grey(), &bitmap_icon_remote, [&nav](){ nav.push(); } }, }); diff --git a/sdcard/PLAYLIST.TXT b/sdcard/PLAYLIST/PLAYLIST.PPL similarity index 75% rename from sdcard/PLAYLIST.TXT rename to sdcard/PLAYLIST/PLAYLIST.PPL index 8c5b671a..afa1da36 100644 --- a/sdcard/PLAYLIST.TXT +++ b/sdcard/PLAYLIST/PLAYLIST.PPL @@ -1,3 +1,2 @@ -##FREQ FILE SAMPLE RATE 315000000,SAMPLES/TeslaChargePort_US.C16,500000 433920000,SAMPLES/TeslaChargePort_EU_AU.C16,500000