Mercurial > foo_out_sdl
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/foosdk/sdk/foobar2000/foo_sample/playback_state.cpp Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,155 @@ +#include "stdafx.h" +#include "resource.h" +#include <helpers/WindowPositionUtils.h> +#include <helpers/atl-misc.h> + +class CPlaybackStateDemo : public CDialogImpl<CPlaybackStateDemo>, private play_callback_impl_base { +public: + enum {IDD = IDD_PLAYBACK_STATE}; + + BEGIN_MSG_MAP_EX(CPlaybackStateDemo) + MSG_WM_INITDIALOG(OnInitDialog) + COMMAND_HANDLER_EX(IDC_PATTERN, EN_CHANGE, OnPatternChange) + COMMAND_HANDLER_EX(IDCANCEL, BN_CLICKED, OnCancel) + COMMAND_HANDLER_EX(IDC_PLAY, BN_CLICKED, OnPlayClicked) + COMMAND_HANDLER_EX(IDC_PAUSE, BN_CLICKED, OnPauseClicked) + COMMAND_HANDLER_EX(IDC_STOP, BN_CLICKED, OnStopClicked) + COMMAND_HANDLER_EX(IDC_PREV, BN_CLICKED, OnPrevClicked) + COMMAND_HANDLER_EX(IDC_NEXT, BN_CLICKED, OnNextClicked) + COMMAND_HANDLER_EX(IDC_RAND, BN_CLICKED, OnRandClicked) + MSG_WM_CONTEXTMENU(OnContextMenu) + END_MSG_MAP() +private: + + // Playback callback methods. + void on_playback_starting(play_control::t_track_command p_command,bool p_paused) {update();} + void on_playback_new_track(metadb_handle_ptr p_track) {update();} + void on_playback_stop(play_control::t_stop_reason p_reason) {update();} + void on_playback_seek(double p_time) {update();} + void on_playback_pause(bool p_state) {update();} + void on_playback_edited(metadb_handle_ptr p_track) {update();} + void on_playback_dynamic_info(const file_info & p_info) {update();} + void on_playback_dynamic_info_track(const file_info & p_info) {update();} + void on_playback_time(double p_time) {update();} + void on_volume_change(float p_new_val) {} + + void update(); + + void OnPatternChange(UINT, int, CWindow); + void OnCancel(UINT, int, CWindow); + + void OnPlayClicked(UINT, int, CWindow) {m_playback_control->start();} + void OnStopClicked(UINT, int, CWindow) {m_playback_control->stop();} + void OnPauseClicked(UINT, int, CWindow) {m_playback_control->toggle_pause();} + void OnPrevClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_prev);} + void OnNextClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_next);} + void OnRandClicked(UINT, int, CWindow) {m_playback_control->start(playback_control::track_command_rand);} + + void OnContextMenu(CWindow wnd, CPoint point); + + BOOL OnInitDialog(CWindow, LPARAM); + + titleformat_object::ptr m_script; + + static_api_ptr_t<playback_control> m_playback_control; +}; + +void CPlaybackStateDemo::OnCancel(UINT, int, CWindow) { + DestroyWindow(); +} + +void CPlaybackStateDemo::OnPatternChange(UINT, int, CWindow) { + m_script.release(); // pattern has changed, force script recompilation + update(); +} + +BOOL CPlaybackStateDemo::OnInitDialog(CWindow, LPARAM) { + update(); + SetDlgItemText(IDC_PATTERN, _T("%codec% | %bitrate% kbps | %samplerate% Hz | %channels% | %playback_time%[ / %length%]$if(%ispaused%, | paused,)")); + ::ShowWindowCentered(*this,GetParent()); // Function declared in SDK helpers. + return TRUE; +} + +void CPlaybackStateDemo::update() { + if (m_script.is_empty()) { + pfc::string8 pattern; + uGetDlgItemText(*this, IDC_PATTERN, pattern); + static_api_ptr_t<titleformat_compiler>()->compile_safe_ex(m_script, pattern); + } + pfc::string_formatter state; + if (m_playback_control->playback_format_title(NULL, state, m_script, NULL, playback_control::display_level_all)) { + //Succeeded already. + } else if (m_playback_control->is_playing()) { + //Starting playback but not done opening the first track yet. + state = "Opening..."; + } else { + state = "Stopped."; + } + uSetDlgItemText(*this, IDC_STATE, state); +} + +void CPlaybackStateDemo::OnContextMenu(CWindow wnd, CPoint point) { + try { + if (wnd == GetDlgItem(IDC_CONTEXTMENU)) { + + // handle the context menu key case - center the menu + if (point == CPoint(-1, -1)) { + CRect rc; + WIN32_OP(wnd.GetWindowRect(&rc)); + point = rc.CenterPoint(); + } + + metadb_handle_list items; + + { // 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. + metadb_handle_ptr item; + if (m_playback_control->get_now_playing(item)) items += item; + } + + CMenuDescriptionHybrid menudesc(*this); //this class manages all the voodoo necessary for descriptions of our menu items to show in the status bar. + + static_api_ptr_t<contextmenu_manager> api; + CMenu menu; + WIN32_OP(menu.CreatePopupMenu()); + enum { + ID_TESTCMD = 1, + ID_CM_BASE, + }; + menu.AppendMenu(MF_STRING, ID_TESTCMD, _T("Test command")); + menudesc.Set(ID_TESTCMD, "This is a test command."); + menu.AppendMenu(MF_SEPARATOR); + + if (items.get_count() > 0) { + api->init_context(items, 0); + api->win32_build_menu(menu, ID_CM_BASE, ~0); + menudesc.SetCM(api.get_ptr(), ID_CM_BASE, ~0); + } else { + menu.AppendMenu(MF_STRING|MF_GRAYED|MF_DISABLED, (UINT_PTR)0, _T("No items selected")); + } + + int cmd = menu.TrackPopupMenu(TPM_RIGHTBUTTON|TPM_NONOTIFY|TPM_RETURNCMD,point.x,point.y,menudesc,0); + if (cmd > 0) { + if (cmd >= ID_CM_BASE) { + api->execute_by_id(cmd - ID_CM_BASE); + } else switch(cmd) { + case ID_TESTCMD: + popup_message::g_show("Blah!", "Test"); + break; + } + } + + } + } catch(std::exception const & e) { + console::complain("Context menu failure", e); //rare + } +} + +void RunPlaybackStateDemo() { + try { + // ImplementModelessTracking registers our dialog to receive dialog messages thru main app loop's IsDialogMessage(). + // 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). + new CWindowAutoLifetime<ImplementModelessTracking<CPlaybackStateDemo> >(core_api::get_main_window()); + } catch(std::exception const & e) { + popup_message::g_complain("Dialog creation failure", e); + } +}
