comparison foosdk/sdk/foobar2000/SDK/play_callback.h @ 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 #pragma once
2 #include "callback_merit.h"
3
4 // IMPLEMENTATION NOTE: all callback methods declared here could not be declared noexcept for historical reasons, but it's strongly recommended that your overrides of these methods are noexcept.
5
6 /*!
7 Class receiving notifications about playback events. Note that all methods are called only from app's main thread.
8 Use play_callback_manager to register your dynamically created instances. Statically registered version is available too - see play_callback_static.
9 */
10 class NOVTABLE play_callback {
11 public:
12 //! Playback process is being initialized. on_playback_new_track() should be called soon after this when first file is successfully opened for decoding.
13 virtual void on_playback_starting(play_control::t_track_command p_command,bool p_paused) = 0;
14 //! Playback advanced to new track.
15 virtual void on_playback_new_track(metadb_handle_ptr p_track) = 0;
16 //! Playback stopped.
17 virtual void on_playback_stop(play_control::t_stop_reason p_reason) = 0;
18 //! User has seeked to specific time.
19 virtual void on_playback_seek(double p_time) = 0;
20 //! Called on pause/unpause.
21 virtual void on_playback_pause(bool p_state) = 0;
22 //! Called when currently played file gets edited.
23 virtual void on_playback_edited(metadb_handle_ptr p_track) = 0;
24 //! Dynamic info (VBR bitrate etc) change.
25 virtual void on_playback_dynamic_info(const file_info & p_info) = 0;
26 //! Per-track dynamic info (stream track titles etc) change. Happens less often than on_playback_dynamic_info().
27 virtual void on_playback_dynamic_info_track(const file_info & p_info) = 0;
28 //! Called every second, for time display
29 virtual void on_playback_time(double p_time) = 0;
30 //! User changed volume settings. Possibly called when not playing.
31 //! @param p_new_val new volume level in dB; 0 for full volume.
32 virtual void on_volume_change(float p_new_val) = 0;
33
34 enum {
35 flag_on_playback_starting = 1 << 0,
36 flag_on_playback_new_track = 1 << 1,
37 flag_on_playback_stop = 1 << 2,
38 flag_on_playback_seek = 1 << 3,
39 flag_on_playback_pause = 1 << 4,
40 flag_on_playback_edited = 1 << 5,
41 flag_on_playback_dynamic_info = 1 << 6,
42 flag_on_playback_dynamic_info_track = 1 << 7,
43 flag_on_playback_time = 1 << 8,
44 flag_on_volume_change = 1 << 9,
45
46 flag_on_playback_all = flag_on_playback_starting | flag_on_playback_new_track |
47 flag_on_playback_stop | flag_on_playback_seek |
48 flag_on_playback_pause | flag_on_playback_edited |
49 flag_on_playback_dynamic_info | flag_on_playback_dynamic_info_track | flag_on_playback_time,
50 };
51 protected:
52 play_callback() {}
53 ~play_callback() {}
54 };
55
56 //! Standard API (always present); manages registrations of dynamic play_callbacks. \n
57 //! Usage: use play_callback_manager::get() to obtain on instance. \n
58 //! Do not reimplement.
59 class NOVTABLE play_callback_manager : public service_base {
60 FB2K_MAKE_SERVICE_COREAPI(play_callback_manager);
61 public:
62 //! Registers a play_callback object.
63 //! @param p_callback Interface to register.
64 //! @param p_flags Indicates which notifications are requested.
65 //! @param p_forward_status_on_register Set to true to have the callback immediately receive current playback status as notifications if playback is active (eg. to receive info about playback process that started before our callback was registered).
66 virtual void register_callback(play_callback * p_callback,unsigned p_flags,bool p_forward_status_on_register) = 0;
67 //! Unregisters a play_callback object.
68 //! @p_callback Previously registered interface to unregister.
69 virtual void unregister_callback(play_callback * p_callback) = 0;
70 };
71
72 //! \since 2.0
73 class NOVTABLE play_callback_manager_v2 : public play_callback_manager {
74 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(play_callback_manager_v2, play_callback_manager);
75 public:
76 virtual void set_callback_merit(play_callback*, fb2k::callback_merit_t) = 0;
77 };
78
79 //! Implementation helper.
80 class play_callback_impl_base : public play_callback {
81 public:
82 play_callback_impl_base(unsigned p_flags = 0xFFFFFFFF) {
83 if (p_flags != 0) play_callback_manager::get()->register_callback(this,p_flags,false);
84 }
85 ~play_callback_impl_base() {
86 play_callback_manager::get()->unregister_callback(this);
87 }
88 void play_callback_reregister(unsigned flags, bool refresh = false) {
89 auto api = play_callback_manager::get();
90 api->unregister_callback(this);
91 if (flags != 0) api->register_callback(this,flags,refresh);
92 }
93 void on_playback_starting(play_control::t_track_command p_command, bool p_paused) override { (void)p_command; (void)p_paused; }
94 void on_playback_new_track(metadb_handle_ptr p_track) override { (void)p_track; }
95 void on_playback_stop(play_control::t_stop_reason p_reason) override { (void)p_reason; }
96 void on_playback_seek(double p_time) override { (void)p_time; }
97 void on_playback_pause(bool p_state) override { (void)p_state; }
98 void on_playback_edited(metadb_handle_ptr p_track) override { (void)p_track; }
99 void on_playback_dynamic_info(const file_info& p_info) override { (void)p_info; }
100 void on_playback_dynamic_info_track(const file_info& p_info) override { (void)p_info; }
101 void on_playback_time(double p_time) override { (void)p_time; }
102 void on_volume_change(float p_new_val) override { (void)p_new_val; }
103
104 PFC_CLASS_NOT_COPYABLE_EX(play_callback_impl_base)
105 };
106
107 //! Static (autoregistered) version of play_callback. Use play_callback_static_factory_t to register.
108 class play_callback_static : public service_base, public play_callback {
109 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(play_callback_static);
110 public:
111 //! Controls which methods your callback wants called; returned value should not change in run time, you should expect it to be queried only once (on startup). See play_callback::flag_* constants.
112 virtual unsigned get_flags() = 0;
113 };
114
115 template<typename T>
116 class play_callback_static_factory_t : public service_factory_single_t<T> {};
117
118
119 //! Gets notified about tracks being played. Notification occurs when at least 60s of the track has been played, or the track has reached its end after at least 1/3 of it has been played through.
120 //! Use playback_statistics_collector_factory_t to register.
121 class NOVTABLE playback_statistics_collector : public service_base {
122 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(playback_statistics_collector);
123 public:
124 virtual void on_item_played(metadb_handle_ptr p_item) = 0;
125 };
126
127 template<typename T>
128 class playback_statistics_collector_factory_t : public service_factory_single_t<T> {};
129
130
131
132
133 //! Helper providing a simplified interface for receiving playback events, in case your code does not care about the kind of playback event that has occurred; useful typically for GUI/rendering code that just refreshes some control whenever a playback state change occurs.
134 class playback_event_notify : private play_callback_impl_base {
135 public:
136 playback_event_notify(playback_control::t_display_level level = playback_control::display_level_all) : play_callback_impl_base(GrabCBFlags(level)) {}
137
138 static t_uint32 GrabCBFlags(playback_control::t_display_level level) {
139 t_uint32 flags = flag_on_playback_starting | flag_on_playback_new_track | flag_on_playback_stop | flag_on_playback_pause | flag_on_playback_edited | flag_on_volume_change;
140 if (level >= playback_control::display_level_titles) flags |= flag_on_playback_dynamic_info_track;
141 if (level >= playback_control::display_level_all) flags |= flag_on_playback_seek | flag_on_playback_dynamic_info | flag_on_playback_time;
142 return flags;
143 }
144 protected:
145 virtual void on_playback_event() {}
146 private:
147 void on_playback_starting(play_control::t_track_command,bool) override {on_playback_event();}
148 void on_playback_new_track(metadb_handle_ptr) override {on_playback_event();}
149 void on_playback_stop(play_control::t_stop_reason) override {on_playback_event();}
150 void on_playback_seek(double) override {on_playback_event();}
151 void on_playback_pause(bool) override {on_playback_event();}
152 void on_playback_edited(metadb_handle_ptr) override {on_playback_event();}
153 void on_playback_dynamic_info(const file_info &) override {on_playback_event();}
154 void on_playback_dynamic_info_track(const file_info &) override {on_playback_event();}
155 void on_playback_time(double) override {on_playback_event();}
156 void on_volume_change(float) override {on_playback_event();}
157 };
158
159 class playback_volume_notify : private play_callback_impl_base {
160 public:
161 playback_volume_notify() : play_callback_impl_base(flag_on_volume_change) {}
162 // override me
163 void on_volume_change(float p_new_val) override { (void)p_new_val; }
164 };