annotate foosdk/sdk/foobar2000/SDK/output.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 "foobar2000-sdk-pch.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
2 #include "output.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
3 #include "audio_chunk_impl.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
4 #include "dsp.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
5 #include "resampler.h"
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
6
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
7 pfc::string8 output_entry::get_device_name( const GUID & deviceID ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
8 pfc::string8 temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
9 if (!get_device_name(deviceID, temp)) temp = "[unknown device]";
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
10 return temp;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
11 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
12
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
13 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
14 class output_device_enum_callback_getname : public output_device_enum_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
15 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
16 output_device_enum_callback_getname( const GUID & wantID, pfc::string_base & strOut ) : m_strOut(strOut), m_wantID(wantID) {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
17 void on_device(const GUID & p_guid,const char * p_name,unsigned p_name_length) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
18 if (!m_got && p_guid == m_wantID) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
19 m_strOut.set_string(p_name, p_name_length);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
20 m_got = true;
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 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
23 bool m_got = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
24 pfc::string_base & m_strOut;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
25 const GUID m_wantID;
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
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
30 bool output_entry::get_device_name( const GUID & deviceID, pfc::string_base & out ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
31 output_device_enum_callback_getname cb(deviceID, out);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
32 this->enum_devices(cb);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
33 return cb.m_got;
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 bool output_entry::g_find( const GUID & outputID, output_entry::ptr & outObj ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
37 for (auto obj : enumerate()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
38 if (obj->get_guid() == outputID) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
39 outObj = obj; return true;
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 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
42 return false;
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
45 output_entry::ptr output_entry::g_find( const GUID & outputID ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
46 output_entry::ptr ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
47 if (!g_find( outputID, ret ) ) throw exception_output_module_not_found();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
48 return ret;
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
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 bool output::is_progressing_() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
53 output_v4::ptr v4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
54 if ( v4 &= this ) return v4->is_progressing();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
55 return true;
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
58 size_t output::update_v2_() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
59 output_v4::ptr v4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
60 if ( v4 &= this ) return v4->update_v2();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
61 bool bReady = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
62 this->update(bReady);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
63 return bReady ? SIZE_MAX : 0;
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 pfc::eventHandle_t output::get_trigger_event_() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
67 output_v4::ptr v4;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
68 if ( v4 &= this ) return v4->get_trigger_event();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
69 return pfc::eventInvalid;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
70 }
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 size_t output::process_samples_v2_(const audio_chunk& c) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
73 output_v6::ptr v6;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
74 if (v6 &= this) return v6->process_samples_v2(c);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
75 this->process_samples(c);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
76 return c.get_sample_count();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
77 }
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 void output_impl::on_flush_internal() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
80 m_eos = false; m_sent_force_play = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
81 m_incoming_ptr = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
82 m_incoming.set_size(0);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
83 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
84
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
85 void output_impl::flush() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
86 on_flush_internal();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
87 on_flush();
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
90 void output_impl::flush_changing_track() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
91 on_flush_internal();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
92 on_flush_changing_track();
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
95 void output_impl::update(bool & p_ready) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
96 p_ready = update_v2() > 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
97 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
98 size_t output_impl::update_v2() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
99
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
100 // Clear preemptively
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
101 m_can_write = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
102
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
103 on_update();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
104
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
105 // No data yet, nothing to do, want data, can't signal how much because we don't know the format
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
106 if (!m_incoming_spec.is_valid()) return SIZE_MAX;
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 // First chunk in or format change
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
109 if (m_incoming_spec != m_active_spec) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
110 if (get_latency_samples() == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
111 // Ready for new format
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
112 m_sent_force_play = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
113 open(m_incoming_spec);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
114 m_active_spec = m_incoming_spec;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
115 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
116 // Previous format still playing, accept no more data
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
117 this->send_force_play();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
118 return 0;
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
122 // opened for m_incoming_spec stream
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
123
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
124 // Store & update m_can_write on our end
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
125 // We don't know what can_write_samples() actually does, could be expensive, avoid calling it repeatedly
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
126 m_can_write = this->can_write_samples();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
127
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
128 if (m_incoming_ptr < m_incoming.get_size()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
129 t_size delta = pfc::min_t(m_incoming.get_size() - m_incoming_ptr, m_can_write * m_incoming_spec.chanCount);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
130 if (delta > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
131 PFC_ASSERT(!m_sent_force_play);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
132 write(audio_chunk_temp_impl(m_incoming.get_ptr() + m_incoming_ptr, delta / m_incoming_spec.chanCount, m_incoming_spec.sampleRate, m_incoming_spec.chanCount, m_incoming_spec.chanMask));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
133 m_incoming_ptr += delta;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
134 if (m_eos && this->queue_empty()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
135 this->send_force_play();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
136 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
137 }
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 m_can_write -= delta / m_incoming_spec.chanCount;
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 return m_can_write;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
142 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
143
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
144 double output_impl::get_latency() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
145 double ret = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
146 if (m_incoming_spec.is_valid()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
147 ret += audio_math::samples_to_time( (m_incoming.get_size() - m_incoming_ptr) / m_incoming_spec.chanCount, m_incoming_spec.sampleRate );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
148 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
149 if (m_active_spec.is_valid()) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
150 ret += audio_math::samples_to_time( get_latency_samples() , m_active_spec.sampleRate );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
151 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
152 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
153 }
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 void output_impl::force_play() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
156 if ( m_eos ) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
157 m_eos = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
158 if (queue_empty()) send_force_play();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
159 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
160 void output_impl::send_force_play() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
161 if (m_sent_force_play) return;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
162 m_sent_force_play = true;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
163 this->on_force_play();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
164 }
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 static void spec_sanity(audio_chunk::spec_t const& spec) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
167 if (!spec.is_valid()) pfc::throw_exception_with_message< exception_io_data >("Invalid audio stream specifications");
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
168 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
169
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
170 size_t output_impl::process_samples_v2(const audio_chunk& p_chunk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
171 PFC_ASSERT(queue_empty());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
172 PFC_ASSERT(!m_eos);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
173 const auto spec = p_chunk.get_spec();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
174 if (m_incoming_spec != spec) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
175 spec_sanity(spec);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
176 m_incoming_spec = spec;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
177 return 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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
180 auto in = p_chunk.get_sample_count();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
181 if (in > m_can_write) in = m_can_write;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
182 if (in > 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
183 write(audio_chunk_partial_ref(p_chunk, 0, in));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
184 m_can_write -= in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
185 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
186 return in;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
187 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
188
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
189 void output_impl::process_samples(const audio_chunk & p_chunk) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
190 PFC_ASSERT(queue_empty());
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
191 PFC_ASSERT( !m_eos );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
192 const auto spec = p_chunk.get_spec();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
193 size_t taken = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
194 if (m_incoming_spec == spec) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
195 // Try bypassing intermediate buffer
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
196 taken = this->process_samples_v2(p_chunk);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
197 if (taken == p_chunk.get_sample_count()) return; // all written, success
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
198 taken *= spec.chanCount;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
199 } else {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
200 spec_sanity(spec);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
201 m_incoming_spec = spec;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
202 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
203 // Queue what's left for update() to eat later
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
204 m_incoming.set_data_fromptr(p_chunk.get_data() + taken, p_chunk.get_used_size() - taken);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
205 m_incoming_ptr = 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
206 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
207
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
208 void output_v3::get_injected_dsps( dsp_chain_config & dsps ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
209 dsps.remove_all();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
210 }
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 size_t output_v4::update_v2() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
213 bool bReady = false;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
214 update(bReady);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
215 return bReady ? SIZE_MAX : 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
216 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
217
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
218 uint32_t output_entry::get_config_flags_compat() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
219 uint32_t ret = get_config_flags();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
220 if ((ret & (flag_low_latency | flag_high_latency)) == 0) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
221 // output predating flag_high_latency + flag_low_latency
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
222 // if it's old foo_out_upnp, report high latency, otherwise low latency.
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
223 static const GUID guid_foo_out_upnp = { 0x9900b4f6, 0x8431, 0x4b0a, { 0x95, 0x56, 0xa7, 0xfc, 0xb9, 0x5b, 0x74, 0x3 } };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
224 if (this->get_guid() == guid_foo_out_upnp) ret |= flag_high_latency;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
225 else ret |= flag_low_latency;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
226 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
227 return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
228 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
229
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
230 bool output_entry::is_high_latency() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
231 return (this->get_config_flags_compat() & flag_high_latency) != 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
232 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
233
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
234 bool output_entry::is_low_latency() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
235 return (this->get_config_flags_compat() & flag_low_latency) != 0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
236 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
237
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
238 // {EEEB07DE-C2C8-44c2-985C-C85856D96DA1}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
239 const GUID output_id_null =
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
240 { 0xeeeb07de, 0xc2c8, 0x44c2, { 0x98, 0x5c, 0xc8, 0x58, 0x56, 0xd9, 0x6d, 0xa1 } };
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 // {D41D2423-FBB0-4635-B233-7054F79814AB}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
243 const GUID output_id_default =
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
244 { 0xd41d2423, 0xfbb0, 0x4635, { 0xb2, 0x33, 0x70, 0x54, 0xf7, 0x98, 0x14, 0xab } };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
245
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
246 outputCoreConfig_t outputCoreConfig_t::defaults() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
247 outputCoreConfig_t cfg = {};
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
248 cfg.m_bitDepth = 16;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
249 cfg.m_buffer_length = 1.0;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
250 cfg.m_output = output_id_default;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
251 // remaining fields nulled by {}
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
252 return cfg;
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 namespace {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
255 class output_device_list_callback_impl : public output_device_list_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
256 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
257 void onDevice( const char * fullName, const GUID & output, const GUID & device ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
258 f(fullName, output, device);
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
259 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
260 std::function< void ( const char*, const GUID&, const GUID&) > f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
261 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
262
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
263 class output_config_change_callback_impl : public output_config_change_callback {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
264 public:
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
265 void outputConfigChanged() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
266 f();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
267 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
268 std::function<void () > f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
269 };
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
270 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
271 void output_manager_v2::listDevices( std::function< void ( const char*, const GUID&, const GUID&) > f ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
272 output_device_list_callback_impl cb; cb.f = f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
273 this->listDevices( cb );
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
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
276 service_ptr output_manager_v2::addCallback( std::function<void() > f ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
277 output_config_change_callback_impl * obj = new output_config_change_callback_impl();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
278 obj->f = f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
279 this->addCallback( obj );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
280 service_ptr_t<output_manager_v2> selfRef ( this );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
281 return fb2k::callOnRelease( [obj, selfRef] {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
282 selfRef->removeCallback( obj ); delete obj;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
283 } );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
284 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
285
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
286 void output_manager_v2::addCallbackPermanent( std::function<void()> f ) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
287 output_config_change_callback_impl * obj = new output_config_change_callback_impl();
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
288 obj->f = f;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
289 addCallback( obj );
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
290 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
291
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
292 void output_manager::getCoreConfig(outputCoreConfig_t& out) {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
293 getCoreConfig(&out, sizeof(out));
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
294 }
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
295
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
296 outputCoreConfig_t output_manager::getCoreConfig() {
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
297 outputCoreConfig_t ret; getCoreConfig(ret); return ret;
20d02a178406 *: check in everything else
Paper <paper@tflc.us>
parents:
diff changeset
298 }