foobar2000 SDK  2015-01-14
dsp_manager.cpp
Go to the documentation of this file.
1 #include "foobar2000.h"
2 
5  m_config_changed = true;
6 }
7 
9 {
10  //dsp_chain_config::g_instantiate(m_dsp_list,p_data);
11  m_config.copy(p_data);
12  m_config_changed = true;
13 }
14 
15 void dsp_manager::dsp_run(t_dsp_chain::const_iterator p_iter,dsp_chunk_list * p_list,const metadb_handle_ptr & cur_file,unsigned flags,double & latency,abort_callback & p_abort)
16 {
17  p_list->remove_bad_chunks();
18 
19  TRACK_CODE("dsp::run",p_iter->m_dsp->run_abortable(p_list,cur_file,flags,p_abort));
20  TRACK_CODE("dsp::get_latency",latency += p_iter->m_dsp->get_latency());
21 }
22 
23 double dsp_manager::run(dsp_chunk_list * p_list,const metadb_handle_ptr & p_cur_file,unsigned p_flags,abort_callback & p_abort) {
24  TRACK_CALL_TEXT("dsp_manager::run");
25 
26  try {
27 #if defined(_MSC_VER) && defined(_M_IX86)
28  fpu_control_default l_fpu_control;
29 #endif
30  double latency=0;
31  bool done = false;
32 
33  t_dsp_chain::const_iterator flush_mark;
34  if ((p_flags & dsp::END_OF_TRACK) && ! (p_flags & dsp::FLUSH)) {
35  for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
36  if (iter->m_dsp->need_track_change_mark()) flush_mark = iter;
37  }
38  }
39 
40  if (m_config_changed)
41  {
42  t_dsp_chain newchain;
43  bool recycle_available = true;
44 
45  for(t_size n=0;n<m_config.get_count();n++) {
46  service_ptr_t<dsp> temp;
47 
48  const dsp_preset & preset = m_config.get_item(n);
49  if (dsp_entry::g_dsp_exists(preset.get_owner())) {
50  t_dsp_chain::iterator iter = newchain.insert_last();
51  iter->m_preset = m_config.get_item(n);
52  iter->m_recycle_flag = false;
53  }
54  }
55 
56 
57  //HACK: recycle existing DSPs in a special case when user has apparently only altered settings of one of DSPs.
58  if (newchain.get_count() == m_chain.get_count()) {
59  t_size data_mismatch_count = 0;
60  t_size owner_mismatch_count = 0;
61  t_dsp_chain::iterator iter_src, iter_dst;
62  iter_src = m_chain.first(); iter_dst = newchain.first();
63  while(iter_src.is_valid() && iter_dst.is_valid()) {
64  if (iter_src->m_preset.get_owner() != iter_dst->m_preset.get_owner()) {
65  owner_mismatch_count++;
66  } else if (iter_src->m_preset != iter_dst->m_preset) {
67  data_mismatch_count++;
68  }
69  ++iter_src; ++iter_dst;
70  }
71  recycle_available = (owner_mismatch_count == 0 && data_mismatch_count <= 1);
72  } else {
73  recycle_available = false;
74  }
75 
76  if (recycle_available) {
77  t_dsp_chain::iterator iter_src, iter_dst;
78  iter_src = m_chain.first(); iter_dst = newchain.first();
79  while(iter_src.is_valid() && iter_dst.is_valid()) {
80  if (iter_src->m_preset == iter_dst->m_preset) {
81  iter_src->m_recycle_flag = true;
82  iter_dst->m_dsp = iter_src->m_dsp;
83  }
84  ++iter_src; ++iter_dst;
85  }
86  }
87 
88  for(t_dsp_chain::iterator iter = newchain.first(); iter.is_valid(); ++iter) {
89  if (iter->m_dsp.is_empty()) {
90  if (!dsp_entry::g_instantiate(iter->m_dsp,iter->m_preset)) uBugCheck();
91  }
92  }
93 
94  if (m_chain.get_count()>0) {
95  bool flushflag = flush_mark.is_valid();
96  for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
97  unsigned flags2 = p_flags;
98  if (iter == flush_mark) flushflag = false;
99  if (flushflag || !iter->m_recycle_flag) flags2|=dsp::FLUSH;
100  dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
101  }
102  done = true;
103  }
104 
105  m_chain = newchain;
106  m_config_changed = false;
107  }
108 
109  if (!done)
110  {
111  bool flushflag = flush_mark.is_valid();
112  for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
113  unsigned flags2 = p_flags;
114  if (iter == flush_mark) flushflag = false;
115  if (flushflag) flags2|=dsp::FLUSH;
116  dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
117  }
118  done = true;
119  }
120 
121  p_list->remove_bad_chunks();
122 
123  return latency;
124  } catch(...) {
125  p_list->remove_all();
126  throw;
127  }
128 }
129 
131 {
132  for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
133  TRACK_CODE("dsp::flush",iter->m_dsp->flush());
134  }
135 }
136 
137 
138 bool dsp_manager::is_active() const {return m_config.get_count()>0;}
139 
142  get_core_settings(cfg);
143 
144  bool found = false;
145  bool changed = false;
146  t_size n,m = cfg.get_count();
147  for(n=0;n<m;n++) {
148  if (cfg.get_item(n).get_owner() == preset.get_owner()) {
149  found = true;
150  if (cfg.get_item(n) != preset) {
151  cfg.replace_item(preset,n);
152  changed = true;
153  }
154  break;
155  }
156  }
157  if (!found) {cfg.insert_item(preset,0); changed = true;}
158 
159  if (changed) set_core_settings(cfg);
160 }
163  get_core_settings(cfg);
164 
165  t_size n,m = cfg.get_count();
166  bit_array_bittable mask(m);
167  bool changed = false;
168  for(n=0;n<m;n++) {
169  bool axe = (cfg.get_item(n).get_owner() == id) ? true : false;
170  if (axe) changed = true;
171  mask.set(n,axe);
172  }
173  if (changed) {
174  cfg.remove_mask(mask);
175  set_core_settings(cfg);
176  }
177 }
178 
181  get_core_settings(cfg);
182  for(t_size n=0;n<cfg.get_count();n++) {
183  const dsp_preset & entry = cfg.get_item(n);
184  if (entry.get_owner() == id) {
185  out = entry; return true;
186  }
187  }
188  return false;
189 }
void remove_all()
Definition: dsp.h:12
Interface to a DSP chunk list. A DSP chunk list object is passed to the DSP chain each time...
Definition: dsp.h:2
Definition: pfc.h:53
void flush()
Flushes the DSP (e.g. when seeking).
t_dsp_chain m_chain
Definition: dsp_manager.h:28
Flush everything.
Definition: dsp.h:52
Generic variable bit_array implementation. Needs to be initialized with requested array size before ...
void core_disable_dsp(const GUID &id)
Helper - disables a DSP in core playback settings.
void insert_item(const dsp_preset &p_data, t_size p_index)
Definition: dsp.cpp:203
void set(t_size n, bool val)
void remove_bad_chunks()
Definition: dsp.cpp:60
void replace_item(const dsp_preset &p_data, t_size p_index)
Definition: dsp.cpp:198
bool is_valid() const
Definition: iterators.h:24
t_size get_count() const
Definition: chain_list_v2.h:61
Flush whatever you need to when tracks change.
Definition: dsp.h:50
size_t t_size
Definition: int_types.h:48
void set_config(const dsp_chain_config &p_data)
Alters the DSP chain configuration. Should be called before the first run() to set the configuration ...
Definition: dsp_manager.cpp:8
static bool g_dsp_exists(const GUID &p_guid)
Definition: dsp.cpp:103
bool is_active() const
Returns whether there's at least one active DSP in the configuration.
virtual GUID get_owner() const =0
static bool g_instantiate(service_ptr_t< dsp > &p_out, const dsp_preset &p_preset)
Definition: dsp.cpp:79
void remove_mask(const bit_array &p_mask)
Definition: dsp.cpp:208
bool core_query_dsp(const GUID &id, dsp_preset &out)
Helper - if a DSP with the specified identifier is present in playback settings, retrieves its config...
void core_enable_dsp(const dsp_preset &preset)
Helper - enables a DSP in core playback settings.
void dsp_run(t_dsp_chain::const_iterator p_iter, dsp_chunk_list *list, const metadb_handle_ptr &cur_file, unsigned flags, double &latency, abort_callback &)
Definition: dsp_manager.cpp:15
void copy(const dsp_chain_config &p_source)
Definition: dsp.cpp:251
t_size get_count() const
Definition: dsp.cpp:188
const dsp_preset & get_item(t_size p_index) const
Definition: dsp.cpp:193
dsp_chain_config_impl m_config
Definition: dsp_manager.h:29
PFC_NORETURN void SHARED_EXPORT uBugCheck()
virtual void get_core_settings(dsp_chain_config &p_out)=0
Retrieves current core playback DSP settings.
bool m_config_changed
Definition: dsp_manager.h:30
double run(dsp_chunk_list *p_list, const metadb_handle_ptr &p_cur_file, unsigned p_flags, abort_callback &p_abort)
Runs DSP on the specified chunk list.
Definition: dsp_manager.cpp:23
virtual void set_core_settings(const dsp_chain_config &p_data)=0
Changes current core playback DSP settings.
void close()
Equivalent to set_config() with empty configuration.
Definition: dsp_manager.cpp:3