foobar2000 SDK  2015-08-03
output.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
4  pfc::string8 temp;
5  if (!get_device_name(deviceID, temp)) temp = "[unknown device]";
6  return std::move(temp);
7 }
8 
9 namespace {
10  class output_device_enum_callback_getname : public output_device_enum_callback {
11  public:
12  output_device_enum_callback_getname( const GUID & wantID, pfc::string_base & strOut ) : m_wantID(wantID), m_got(), m_strOut(strOut) {}
13  void on_device(const GUID & p_guid,const char * p_name,unsigned p_name_length) {
14  if (!m_got && p_guid == m_wantID) {
15  m_strOut.set_string(p_name, p_name_length);
16  m_got = true;
17  }
18  }
19  bool m_got;
20  pfc::string_base & m_strOut;
21  const GUID m_wantID;
22  };
23 
24 }
25 
26 bool output_entry::get_device_name( const GUID & deviceID, pfc::string_base & out ) {
27  output_device_enum_callback_getname cb(deviceID, out);
28  this->enum_devices(cb);
29  return cb.m_got;
30 }
31 
32 bool output_entry::g_find( const GUID & outputID, output_entry::ptr & outObj ) {
33  service_enum_t<output_entry> e; output_entry::ptr obj;
34  while(e.next(obj)) {
35  if (obj->get_guid() == outputID) {
36  outObj = obj; return true;
37  }
38  }
39  return false;
40 }
41 
42 output_entry::ptr output_entry::g_find( const GUID & outputID ) {
43  output_entry::ptr ret;
44  if (!g_find( outputID, ret ) ) throw exception_output_module_not_found();
45  return ret;
46 }
47 
48 
49 
50 
51 
53  m_incoming_ptr = 0;
54  m_incoming.set_size(0);
55  on_flush();
56 }
58  m_incoming_ptr = 0;
59  m_incoming.set_size(0);
60  on_flush_changing_track();
61 }
62 void output_impl::update(bool & p_ready) {
63  on_update();
64  if (m_incoming_spec != m_active_spec && m_incoming_ptr < m_incoming.get_size()) {
65  if (get_latency_samples() == 0) {
66  open(m_incoming_spec);
67  m_active_spec = m_incoming_spec;
68  } else {
69  force_play();
70  }
71  }
72  if (m_incoming_spec == m_active_spec && m_incoming_ptr < m_incoming.get_size()) {
73  t_size cw = can_write_samples() * m_incoming_spec.m_channels;
74  t_size delta = pfc::min_t(m_incoming.get_size() - m_incoming_ptr,cw);
75  if (delta > 0) {
76  write(audio_chunk_temp_impl(m_incoming.get_ptr()+m_incoming_ptr,delta / m_incoming_spec.m_channels,m_incoming_spec.m_sample_rate,m_incoming_spec.m_channels,m_incoming_spec.m_channel_config));
77  m_incoming_ptr += delta;
78  }
79  }
80  p_ready = (m_incoming_ptr == m_incoming.get_size());
81 }
83  double ret = 0;
84  if (m_incoming_spec.is_valid()) {
85  ret += audio_math::samples_to_time( (m_incoming.get_size() - m_incoming_ptr) / m_incoming_spec.m_channels, m_incoming_spec.m_sample_rate );
86  }
87  if (m_active_spec.is_valid()) {
88  ret += audio_math::samples_to_time( get_latency_samples() , m_active_spec.m_sample_rate );
89  }
90  return ret;
91 }
93  pfc::dynamic_assert(m_incoming_ptr == m_incoming.get_size());
94  t_samplespec spec;
95  spec.fromchunk(p_chunk);
96  if (!spec.is_valid()) pfc::throw_exception_with_message< exception_io_data >("Invalid audio stream specifications");
97  m_incoming_spec = spec;
98  t_size length = p_chunk.get_used_size();
99  m_incoming.set_data_fromptr(p_chunk.get_data(),length);
100  m_incoming_ptr = 0;
101 }
102 
103 
104 // {EEEB07DE-C2C8-44c2-985C-C85856D96DA1}
106 { 0xeeeb07de, 0xc2c8, 0x44c2, { 0x98, 0x5c, 0xc8, 0x58, 0x56, 0xd9, 0x6d, 0xa1 } };
107 
108 // {D41D2423-FBB0-4635-B233-7054F79814AB}
110 { 0xd41d2423, 0xfbb0, 0x4635, { 0xb2, 0x33, 0x70, 0x54, 0xf7, 0x98, 0x14, 0xab } };
111 
113  outputCoreConfig_t cfg = {};
114  cfg.m_bitDepth = 16;
115  cfg.m_buffer_length = 1.0;
117  // remaining fields nulled by {}
118  return cfg;
119 }
T min_t(const T &item1, const T &item2)
Definition: primitives.h:556
audio_chunk_memref_impl audio_chunk_temp_impl
Definition: audio_chunk.h:310
Definition: pfc.h:71
void flush_changing_track()
Definition: output.cpp:57
const GUID output_id_null
Definition: output.cpp:105
void update(bool &p_ready)
Updates playback; queries whether the device is ready to receive new data.
Definition: output.cpp:62
pfc::string8 get_device_name(const GUID &deviceID)
Definition: output.cpp:3
Interface to container of a chunk of audio data. See audio_chunk_impl for an implementation.
Definition: audio_chunk.h:5
void process_samples(const audio_chunk &p_chunk)
Sends new samples to the device. Allowed to be called only when update() indicates that the device is...
Definition: output.cpp:92
const GUID output_id_default
Definition: output.cpp:109
void fromchunk(const audio_chunk &p_chunk)
Definition: output.h:82
static bool g_find(const GUID &outputID, output_entry::ptr &outObj)
Definition: output.cpp:32
void flush()
Flushes queued audio data. Called after seeking.
Definition: output.cpp:52
double get_latency()
Retrieves amount of audio data queued for playback, in seconds.
Definition: output.cpp:82
void dynamic_assert(bool p_condition, const char *p_msg)
Definition: primitives.h:239
size_t t_size
Definition: int_types.h:48
double m_buffer_length
Definition: output.h:264
virtual void enum_devices(output_device_enum_callback &p_callback)=0
Enumerates devices supported by this output_entry implementation.
virtual audio_sample * get_data()=0
Retrieves audio data buffer pointer (non-const version). Returned pointer is for temporary use only; ...
static outputCoreConfig_t defaults()
Definition: output.cpp:112
void write(const service_ptr_t< file > &p_file, abort_callback &p_abort, const char *p_string, bool is_utf8)
uint32_t m_bitDepth
Definition: output.h:266
bool next(service_ptr_t< t_query > &p_out)
Definition: service.h:587
size_t get_used_size() const
Returns actual amount of audio data contained in the buffer (sample count * channel count)...
Definition: audio_chunk.h:134