annotate foosdk/sdk/foobar2000/SDK/output.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
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 #pragma once
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include <functional>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 PFC_DECLARE_EXCEPTION(exception_output_device_not_found, pfc::exception, "Audio device not found")
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6 PFC_DECLARE_EXCEPTION(exception_output_module_not_found, exception_output_device_not_found, "Output module not found")
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 PFC_DECLARE_EXCEPTION(exception_output_invalidated, pfc::exception, "Audio device invalidated")
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 PFC_DECLARE_EXCEPTION(exception_output_device_in_use, pfc::exception, "Audio device in use")
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 PFC_DECLARE_EXCEPTION(exception_output_unsupported_stream_format, pfc::exception, "Unsupported audio stream format")
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 //! Output interrupted due to another application taking exclusive access to the device - do not complain to user.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12 PFC_DECLARE_EXCEPTION(exception_output_interrupted, pfc::exception, "Output interrupted");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 //! Structure describing PCM audio data format, with basic helper functions.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 struct t_pcmspec
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 unsigned m_sample_rate = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 unsigned m_bits_per_sample = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 unsigned m_channels = 0,m_channel_config = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 bool m_float = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
21
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
22 inline unsigned align() const {return (m_bits_per_sample / 8) * m_channels;}
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 uint64_t time_to_bytes(double p_time) const {return audio_math::time_to_samples(p_time,m_sample_rate) * (m_bits_per_sample / 8) * m_channels;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 double bytes_to_time(uint64_t p_bytes) const {return (double) (p_bytes / ((m_bits_per_sample / 8) * m_channels)) / (double) m_sample_rate;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
26
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
27 inline bool operator==(/*const t_pcmspec & p_spec1,*/const t_pcmspec & p_spec2) const
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
28 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
29 return /*p_spec1.*/m_sample_rate == p_spec2.m_sample_rate
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 && /*p_spec1.*/m_bits_per_sample == p_spec2.m_bits_per_sample
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 && /*p_spec1.*/m_channels == p_spec2.m_channels
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 && /*p_spec1.*/m_channel_config == p_spec2.m_channel_config
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 && /*p_spec1.*/m_float == p_spec2.m_float;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
34 }
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 inline bool operator!=(/*const t_pcmspec & p_spec1,*/const t_pcmspec & p_spec2) const
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 return !(*this == p_spec2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 }
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 inline void reset() { *this = t_pcmspec(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 inline bool is_valid() const
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
43 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
44 return m_sample_rate >= 1000 && m_sample_rate <= 1000000 &&
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 m_channels > 0 && m_channels <= 256 && m_channel_config != 0 &&
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 (m_bits_per_sample == 8 || m_bits_per_sample == 16 || m_bits_per_sample == 24 || m_bits_per_sample == 32);
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 };
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 class NOVTABLE output_device_enum_callback
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 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 virtual void on_device(const GUID & p_guid,const char * p_name,unsigned p_name_length) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 };
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 class NOVTABLE output : public service_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
57 FB2K_MAKE_SERVICE_INTERFACE(output,service_base);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 //! Retrieves amount of audio data queued for playback, in seconds.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 virtual double get_latency() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 //! Sends new samples to the device. Allowed to be called only when update() indicates that the device is ready. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 //! update() should be called AGAIN after each process_samples() to know if the device is ready for more. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 //! This method SHOULD NOT block, only copy passed chunk and return immediately.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
64 virtual void process_samples(const audio_chunk & p_chunk) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
65 //! Updates playback; queries whether the device is ready to receive new data. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
66 //! This method SHOULD NOT block, only update internal state and return immediately.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 //! @param p_ready On success, receives value indicating whether the device is ready for next process_samples() call.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 virtual void update(bool & p_ready) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 //! Pauses/unpauses playback.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 virtual void pause(bool p_state) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
71 //! Flushes queued audio data. Called after seeking.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
72 virtual void flush() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 //! Forces playback of queued data. Called when there's no more data to send, to prevent infinite waiting if output implementation starts actually playing after amount of data in internal buffer reaches some level.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 virtual void force_play() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 //! Sets playback volume.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 //! @p_val Volume level in dB. Value of 0 indicates full ("100%") volume, negative values indciate different attenuation levels.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
78 virtual void volume_set(double p_val) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
79
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 //! Helper, see output_v4::is_progressing().
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 bool is_progressing_();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 //! Helper, see output_v4::update_v2()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 size_t update_v2_();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84 //! Helper, see output_v4::get_trigger_event()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 pfc::eventHandle_t get_trigger_event_();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 //! Helper, see output_v6::process_samples_v2()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 size_t process_samples_v2_(const audio_chunk&);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
88
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
89 //! Helper for output_entry implementation.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 static uint32_t g_extra_flags() { return 0; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
93
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
94 class NOVTABLE output_v2 : public output {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 FB2K_MAKE_SERVICE_INTERFACE(output_v2, output);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 //! Obsolete, do not use.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 virtual bool want_track_marks() {return false;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99 //! Obsolete, do not use.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 virtual void on_track_mark() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 //! Obsolete, do not use.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102 virtual void enable_fading(bool) { }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 //! Called when flushing due to manual track change rather than seek-within-track
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104 virtual void flush_changing_track() {flush();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
107 class dsp_chain_config;
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 //! \since 1.4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 class NOVTABLE output_v3 : public output_v2 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 FB2K_MAKE_SERVICE_INTERFACE(output_v3, output_v2);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 //! Does this output require a specific sample rate? If yes, return the value, otherwise return zero. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 //! Returning a nonzero will cause a resampler DSP to be injected.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 virtual unsigned get_forced_sample_rate() { return 0; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 //! Allows the output to inject specific DSPs at the end of the used chain. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 //! Default implementation queries get_forced_sample_rate() and injects a resampler.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 virtual void get_injected_dsps( dsp_chain_config & );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
119 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
120
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
121 //! \since 1.6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 class NOVTABLE output_v4 : public output_v3 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123 FB2K_MAKE_SERVICE_INTERFACE(output_v4, output_v3);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 //! Returns an event handle that becomes signaled once the output wants an update() call and possibly process_samples(). \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 //! Optional; may return pfc::eventInvalid if not available at this time or not supported. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127 //! Use the event only if update() signals that it cannot take any more data at this time. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 virtual pfc::eventHandle_t get_trigger_event() {return pfc::eventInvalid;}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 //! Returns whether the audio stream is currently being played or not. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 //! Typically, for a short period of time, initially sent data is not played until a sufficient amount is queued to initiate playback without glitches. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 //! For old outputs that do not implement this, the value can be assumed to be true.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 virtual bool is_progressing() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 //! Improved version of update(); returns 0 if the output isn't ready to receive any new data, otherwise an advisory number of samples - at the current stream format - that the output expects to take now. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 //! If the caller changes the stream format, the value is irrelevant. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 //! The output may return SIZE_MAX to indicate that it can take data but does not currently have any hints to tell how much. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 //! This method SHOULD NOT block, only update output state and return immediately.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
138 virtual size_t update_v2();
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 //! \since 1.6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 class output_v5 : public output_v4 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143 FB2K_MAKE_SERVICE_INTERFACE(output_v5, output_v4);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 virtual unsigned get_forced_channel_mask() { return 0; }
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 //! \since 2.2
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 class output_v6 : public output_v5 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 FB2K_MAKE_SERVICE_INTERFACE(output_v6, output_v5);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 //! Extended process_samples(), allowed to read only part of the chunk if out of buffer space to take whole.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 //! @returns Number of samples actually taken.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
154 virtual size_t process_samples_v2(const audio_chunk&) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
155 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 //! \since 2.25
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 //! foobar2000 v2.25 functionality draft, use only for testing live info delivery in v2.25 beta.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 class output_v7 : public output_v6 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 FB2K_MAKE_SERVICE_INTERFACE(output_v7, output_v6);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 //! Optional, gets notified about current playback metadata.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 //! @param audioSource can be any type (metadb_handle, metadb_info_container, possibly other), use operator &= to determine type.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 virtual void hint_source(fb2k::objRef audioSource) { (void)audioSource; }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
165 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
166
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 class NOVTABLE output_entry : public service_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 FB2K_MAKE_SERVICE_INTERFACE_ENTRYPOINT(output_entry);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 //! Instantiates output class.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 virtual void instantiate(service_ptr_t<output> & p_out,const GUID & p_device,double p_buffer_length,bool p_dither,t_uint32 p_bitdepth) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 //! Enumerates devices supported by this output_entry implementation.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 virtual void enum_devices(output_device_enum_callback & p_callback) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 //! For internal use by backend. Each output_entry implementation must have its own guid.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 virtual GUID get_guid() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 //! For internal use by backend. Retrieves human-readable name of this output_entry implementation.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 virtual const char * get_name() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
178
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
179 #ifdef _WIN32
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 //! Obsolete, do not use.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 virtual void advanced_settings_popup(HWND,POINT) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 #endif
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 enum {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 flag_needs_bitdepth_config = 1 << 0,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 flag_needs_dither_config = 1 << 1,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 //! Obsolete, do not use.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188 flag_needs_advanced_config = 1 << 2,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 flag_needs_device_list_prefixes = 1 << 3,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 //! Supports playing multiple simultaneous audio streams thru one device?
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 flag_supports_multiple_streams = 1 << 4,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 //! High latency operation (such as remote network playback), mutually exclusive with flag_low_latency
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 flag_high_latency = 1 << 5,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 //! Low latency operation (local playback), mutually exclusive with flag_high_latency
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 flag_low_latency = 1 << 6,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 //! When set, the output will be used in special compatibility mode: guaranteed regular update() calls, injected padding (silence) at the end of stream.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 flag_needs_shims = 1 << 7,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 virtual t_uint32 get_config_flags() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 uint32_t get_config_flags_compat();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 bool is_high_latency();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207 bool is_low_latency();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 pfc::string8 get_device_name( const GUID & deviceID);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 bool get_device_name( const GUID & deviceID, pfc::string_base & out );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
211
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
212 static bool g_find( const GUID & outputID, output_entry::ptr & outObj );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 static output_entry::ptr g_find(const GUID & outputID );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 //! Helper; implements output_entry for specific output class implementation. output_entry methods are forwarded to static methods of your output class. Use output_factory_t<myoutputclass> instead of using this class directly.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217 template<typename T, typename E = output_entry>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 class output_entry_impl_t : public E
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 void instantiate(service_ptr_t<output> & p_out,const GUID & p_device,double p_buffer_length,bool p_dither,t_uint32 p_bitdepth) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 p_out = new service_impl_t<T>(p_device,p_buffer_length,p_dither,p_bitdepth);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 void enum_devices(output_device_enum_callback & p_callback) {T::g_enum_devices(p_callback);}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 GUID get_guid() {return T::g_get_guid();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 const char * get_name() {return T::g_get_name();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 t_uint32 get_config_flags() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229 t_uint32 flags = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 if (T::g_advanced_settings_query()) flags |= output_entry::flag_needs_advanced_config;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 if (T::g_needs_bitdepth_config()) flags |= output_entry::flag_needs_bitdepth_config;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 if (T::g_needs_dither_config()) flags |= output_entry::flag_needs_dither_config;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233 if (T::g_needs_device_list_prefixes()) flags |= output_entry::flag_needs_device_list_prefixes;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 if (T::g_supports_multiple_streams()) flags |= output_entry::flag_supports_multiple_streams;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 if (T::g_is_high_latency()) flags |= output_entry::flag_high_latency;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 else flags |= output_entry::flag_low_latency;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237 flags |= T::g_extra_flags();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 return flags;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
241
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
242
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 //! Use this to register your output implementation.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 template<class T>
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245 class output_factory_t : public service_factory_single_t<output_entry_impl_t<T> > {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 //! Helper base class for output implementations. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 //! This is the preferred way of implementing output. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 //! This is NOT a public interface and its layout changes between foobar2000 SDK versions, do not assume other outputs to implement it.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 class output_impl : public output_v7 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 output_impl() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
253
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
254 //! Called periodically. You can update your state in this method. Can do nothing if not needed.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 virtual void on_update() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 //! Writes an audio chunk to your output. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 //! Will never get more than last can_write_samples() asked for. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 //! Format being send will match last open().
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 virtual void write(const audio_chunk & p_data) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 //! @returns How many samples write() can take at this moment. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 //! It's called immediately after on_update() and can reuse value calculated in last on_update().
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262 virtual t_size can_write_samples() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 //! @returns Current latency, delay between last written sample and currently heard audio.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 virtual t_size get_latency_samples() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 //! Flush output, after seek etc.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 virtual void on_flush() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 //! Flush output due to manual track change in progress. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 //! Same as on_flush() by default.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 virtual void on_flush_changing_track() {on_flush();}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 //! Called before first chunk and on stream format change. \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 //! Following write() calls will deliver chunks in the same format as specified here.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 virtual void open(audio_chunk::spec_t const & p_spec) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
274
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
275 //! Override this, not force_play(). \n
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 //! output_impl will defer call to on_force_play() until out of data in its buffer.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 virtual void on_force_play() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 // base class virtual methods which derived class must also implement
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 // virtual void pause(bool p_state) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 // virtual void volume_set(double p_val) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 // virtual bool is_progressing() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 void on_need_reopen() {m_active_spec.clear(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 void flush() override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 void flush_changing_track() override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 void update(bool & p_ready) override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 size_t update_v2() override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 double get_latency() override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291 void process_samples(const audio_chunk & p_chunk) override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 size_t process_samples_v2(const audio_chunk&) override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 void force_play() override final;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 void on_flush_internal();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295 void send_force_play();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 bool queue_empty() const { return m_incoming_ptr == m_incoming.get_size(); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
299 pfc::array_t<audio_sample,pfc::alloc_fast_aggressive> m_incoming;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
300 size_t m_incoming_ptr = 0, m_can_write = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
301 audio_chunk::spec_t m_incoming_spec,m_active_spec;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
302 bool m_eos = false; // EOS issued by caller / no more data expected until a flush
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
303 bool m_sent_force_play = false; // set if sent on_force_play()
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
304 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
305
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
306
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
307 class NOVTABLE volume_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
308 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
309 virtual void on_volume_scale(float v) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
310 virtual void on_volume_arbitrary(int v) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
311 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
312
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
313 class NOVTABLE volume_control : public service_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
314 FB2K_MAKE_SERVICE_INTERFACE(volume_control, service_base)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
315 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
316 virtual void add_callback(volume_callback * ptr) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
317 virtual void remove_callback(volume_callback * ptr) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
318
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
319 enum style_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
320 styleScale,
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
321 styleArbitrary
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
322 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
323
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
324 virtual style_t getStyle() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
325
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
326 virtual float scaleGet() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
327 virtual void scaleSet(float v) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
328
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
329 virtual void arbitrarySet(int val) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
330 virtual int arbitraryGet() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
331 virtual int arbitraryGetMin() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
332 virtual int arbitraryGetMax() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
333 virtual bool arbitraryGetMute() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
334 virtual void arbitrarySetMute(bool val) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
335 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
336
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
337
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
338 class NOVTABLE output_entry_v2 : public output_entry {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
339 FB2K_MAKE_SERVICE_INTERFACE(output_entry_v2, output_entry)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
340 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
341 virtual bool get_volume_control(const GUID & id, volume_control::ptr & out) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
342 virtual bool hasVisualisation() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
343 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
344
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
345 //! \since 1.5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
346 class NOVTABLE output_devices_notify {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
347 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
348 virtual void output_devices_changed() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
349 protected:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
350 output_devices_notify() {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
351 private:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
352 output_devices_notify(const output_devices_notify &) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
353 void operator=(const output_devices_notify &) = delete;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
354 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
355
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
356 //! \since 1.5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
357 class NOVTABLE output_entry_v3 : public output_entry_v2 {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
358 FB2K_MAKE_SERVICE_INTERFACE(output_entry_v3, output_entry_v2)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
359 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
360
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
361 //! Main thread only!
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
362 virtual void add_notify(output_devices_notify *) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
363 //! Main thread only!
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
364 virtual void remove_notify(output_devices_notify *) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
365
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
366 //! Main thread only!
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
367 virtual void set_pinned_device(const GUID & guid) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
368 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
369
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
370 #pragma pack(push, 1)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
371 //! \since 1.3.5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
372 struct outputCoreConfig_t {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
373
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
374 static outputCoreConfig_t defaults();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
375
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
376 GUID m_output;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
377 GUID m_device;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
378 double m_buffer_length;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
379 uint32_t m_flags;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
380 uint32_t m_bitDepth;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
381 enum { flagUseDither = 1 << 0, flagUseFades = 1 << 1 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
382 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
383 #pragma pack(pop)
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
384
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
385 //! \since 1.3.5
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
386 //! Allows components to access foobar2000 core's output settings.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
387 class NOVTABLE output_manager : public service_base {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
388 FB2K_MAKE_SERVICE_COREAPI(output_manager);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
389 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
390 //! Instantiates an output instance with core settings.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
391 //! @param overrideBufferLength Specify non zero to override user-configured buffer length in core settings.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
392 //! @returns The new output instance. Throws exceptions on failure (invalid settings or other).
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
393 virtual output::ptr instantiateCoreDefault(double overrideBufferLength = 0) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
394 virtual void getCoreConfig( void * out, size_t outSize ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
395
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
396 void getCoreConfig(outputCoreConfig_t& out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
397 outputCoreConfig_t getCoreConfig();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
398 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
399
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
400 //! \since 1.3.16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
401 class NOVTABLE output_device_list_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
402 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
403 virtual void onDevice( const char * fullName, const GUID & output, const GUID & device ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
404 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
405
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
406 //! \since 1.3.16
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
407 class NOVTABLE output_config_change_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
408 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
409 virtual void outputConfigChanged() = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
410 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
411
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
412 //! \since 1.4
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
413 class NOVTABLE output_manager_v2 : public output_manager {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
414 FB2K_MAKE_SERVICE_COREAPI_EXTENSION(output_manager_v2, output_manager);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
415 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
416 virtual void setCoreConfig( const void * in, size_t inSize, bool bSuppressPlaybackRestart = false ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
417 void setCoreConfig( const outputCoreConfig_t & in ) { setCoreConfig(&in, sizeof(in) ); }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
418 virtual void setCoreConfigDevice( const GUID & output, const GUID & device ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
419 virtual void listDevices( output_device_list_callback & callback ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
420 void listDevices( std::function< void ( const char*, const GUID&, const GUID&) > f );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
421 virtual void addCallback( output_config_change_callback * ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
422 virtual void removeCallback( output_config_change_callback * ) = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
423
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
424 service_ptr addCallback( std::function<void()> f );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
425 void addCallbackPermanent( std::function<void()> f );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
426 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
427
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
428 extern const GUID output_id_null;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
429 extern const GUID output_id_default;