Mercurial > foo_out_sdl
comparison foosdk/sdk/foobar2000/foo_sample/playback_state.cpp @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #include "stdafx.h" | |
| 2 #include "resource.h" | |
| 3 #include <helpers/WindowPositionUtils.h> | |
| 4 #include <helpers/atl-misc.h> | |
| 5 | |
| 6 class CPlaybackStateDemo : public CDialogImpl<CPlaybackStateDemo>, private play_callback_impl_base { | |
| 7 public: | |
| 8 enum {IDD = IDD_PLAYBACK_STATE}; | |
| 9 | |
| 10 BEGIN_MSG_MAP_EX(CPlaybackStateDemo) | |
| 11 MSG_WM_INITDIALOG(OnInitDialog) | |
| 12 COMMAND_HANDLER_EX(IDC_PATTERN, EN_CHANGE, OnPatternChange) | |
| 13 COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel) | |
| 14 COMMAND_HANDLER_EX(IDC_PLAY, BN_CLICKED, OnPlayClicked) | |
| 15 COMMAND_HANDLER_EX(IDC_PAUSE, BN_CLICKED, OnPauseClicked) | |
| 16 COMMAND_HANDLER_EX(IDC_STOP, BN_CLICKED, OnStopClicked) | |
| 17 COMMAND_HANDLER_EX(IDC_PREV, BN_CLICKED, OnPrevClicked) | |
| 18 COMMAND_HANDLER_EX(IDC_NEXT, BN_CLICKED, OnNextClicked) | |
| 19 COMMAND_HANDLER_EX(IDC_RAND, BN_CLICKED, OnRandClicked) | |
| 20 MSG_WM_CONTEXTMENU(OnContextMenu) | |
| 21 END_MSG_MAP() | |
| 22 private: | |
| 23 | |
| 24 // Playback callback methods. | |
| 25 void on_playback_starting(play_control::t_track_command p_command,bool p_paused) {update();} | |
| 26 void on_playback_new_track(metadb_handle_ptr p_track) {update();} | |
| 27 void on_playback_stop(play_control::t_stop_reason p_reason) {update();} | |
| 28 void on_playback_seek(double p_time) {update();} | |
| 29 void on_playback_pause(bool p_state) {update();} | |
| 30 void on_playback_edited(metadb_handle_ptr p_track) {update();} | |
| 31 void on_playback_dynamic_info(const file_info & p_info) {update();} | |
| 32 void on_playback_dynamic_info_track(const file_info & p_info) {update();} | |
| 33 void on_playback_time(double p_time) {update();} | |
| 34 void on_volume_change(float p_new_val) {} | |
| 35 | |
| 36 void update(); | |
| 37 | |
| 38 void OnPatternChange(UINT, int, CWindow); | |
| 39 void OnCancel(UINT, int, CWindow); | |
| 40 | |
| 41 void OnPlayClicked(UINT, int, CWindow) {m_playback_control->start();} | |
| 42 void OnStopClicked(UINT, int, CWindow) {m_playback_control->stop();} | |
| 43 void OnPauseClicked(UINT, int, CWindow) {m_playback_control->toggle_pause();} | |
| 44 void OnPrevClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_prev);} | |
| 45 void OnNextClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_next);} | |
| 46 void OnRandClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_rand);} | |
| 47 | |
| 48 void OnContextMenu(CWindow wnd, CPoint point); | |
| 49 | |
| 50 BOOL OnInitDialog(CWindow, LPARAM); | |
| 51 | |
| 52 titleformat_object::ptr m_script; | |
| 53 | |
| 54 static_api_ptr_t<playback_control> m_playback_control; | |
| 55 }; | |
| 56 | |
| 57 void CPlaybackStateDemo::OnCancel(UINT, int, CWindow) { | |
| 58 DestroyWindow(); | |
| 59 } | |
| 60 | |
| 61 void CPlaybackStateDemo::OnPatternChange(UINT, int, CWindow) { | |
| 62 m_script.release(); // pattern has changed, force script recompilation | |
| 63 update(); | |
| 64 } | |
| 65 | |
| 66 BOOL CPlaybackStateDemo::OnInitDialog(CWindow, LPARAM) { | |
| 67 update(); | |
| 68 SetDlgItemText(IDC_PATTERN, _T("%codec% | %bitrate% kbps | %samplerate% Hz | %channels% | %playback_time%[ / %length%]$if(%ispaused%, | paused,)")); | |
| 69 ::ShowWindowCentered(*this,GetParent()); // Function declared in SDK helpers. | |
| 70 return TRUE; | |
| 71 } | |
| 72 | |
| 73 void CPlaybackStateDemo::update() { | |
| 74 if (m_script.is_empty()) { | |
| 75 pfc::string8 pattern; | |
| 76 uGetDlgItemText(*this, IDC_PATTERN, pattern); | |
| 77 static_api_ptr_t<titleformat_compiler>()->compile_safe_ex(m_script, pattern); | |
| 78 } | |
| 79 pfc::string_formatter state; | |
| 80 if (m_playback_control->playback_format_title(NULL, state, m_script, NULL, playback_control::display_level_all)) { | |
| 81 //Succeeded already. | |
| 82 } else if (m_playback_control->is_playing()) { | |
| 83 //Starting playback but not done opening the first track yet. | |
| 84 state = "Opening..."; | |
| 85 } else { | |
| 86 state = "Stopped."; | |
| 87 } | |
| 88 uSetDlgItemText(*this, IDC_STATE, state); | |
| 89 } | |
| 90 | |
| 91 void CPlaybackStateDemo::OnContextMenu(CWindow wnd, CPoint point) { | |
| 92 try { | |
| 93 if (wnd == GetDlgItem(IDC_CONTEXTMENU)) { | |
| 94 | |
| 95 // handle the context menu key case - center the menu | |
| 96 if (point == CPoint(-1, -1)) { | |
| 97 CRect rc; | |
| 98 WIN32_OP(wnd.GetWindowRect(&rc)); | |
| 99 point = rc.CenterPoint(); | |
| 100 } | |
| 101 | |
| 102 metadb_handle_list items; | |
| 103 | |
| 104 { // note: we would normally just use contextmenu_manager::init_context_now_playing(), but we go the "make the list ourselves" route to demonstrate how to invoke the menu for arbitrary items. | |
| 105 metadb_handle_ptr item; | |
| 106 if (m_playback_control->get_now_playing(item)) items += item; | |
| 107 } | |
| 108 | |
| 109 CMenuDescriptionHybrid menudesc(*this); //this class manages all the voodoo necessary for descriptions of our menu items to show in the status bar. | |
| 110 | |
| 111 static_api_ptr_t<contextmenu_manager> api; | |
| 112 CMenu menu; | |
| 113 WIN32_OP(menu.CreatePopupMenu()); | |
| 114 enum { | |
| 115 ID_TESTCMD = 1, | |
| 116 ID_CM_BASE, | |
| 117 }; | |
| 118 menu.AppendMenu(MF_STRING, ID_TESTCMD, _T("Test command")); | |
| 119 menudesc.Set(ID_TESTCMD, "This is a test command."); | |
| 120 menu.AppendMenu(MF_SEPARATOR); | |
| 121 | |
| 122 if (items.get_count() > 0) { | |
| 123 api->init_context(items, 0); | |
| 124 api->win32_build_menu(menu, ID_CM_BASE, ~0); | |
| 125 menudesc.SetCM(api.get_ptr(), ID_CM_BASE, ~0); | |
| 126 } else { | |
| 127 menu.AppendMenu(MF_STRING|MF_GRAYED|MF_DISABLED, (UINT_PTR)0, _T("No items selected")); | |
| 128 } | |
| 129 | |
| 130 int cmd = menu.TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD,point.x,point.y,menudesc,0); | |
| 131 if (cmd > 0) { | |
| 132 if (cmd >= ID_CM_BASE) { | |
| 133 api->execute_by_id(cmd - ID_CM_BASE); | |
| 134 } else switch(cmd) { | |
| 135 case ID_TESTCMD: | |
| 136 popup_message::g_show("Blah!", "Test"); | |
| 137 break; | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 } | |
| 142 } catch(std::exception const & e) { | |
| 143 console::complain("Context menu failure", e); //rare | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 void RunPlaybackStateDemo() { | |
| 148 try { | |
| 149 // ImplementModelessTracking registers our dialog to receive dialog messages thru main app loop's IsDialogMessage(). | |
| 150 // CWindowAutoLifetime creates the window in the constructor (taking the parent window as a parameter) and deletes the object when the window has been destroyed (through WTL's OnFinalMessage). | |
| 151 new CWindowAutoLifetime<ImplementModelessTracking<CPlaybackStateDemo> >(core_api::get_main_window()); | |
| 152 } catch(std::exception const & e) { | |
| 153 popup_message::g_complain("Dialog creation failure", e); | |
| 154 } | |
| 155 } |
