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