latest SDK
This commit is contained in:
209
foobar2000/SDK/dsp_manager.cpp
Normal file
209
foobar2000/SDK/dsp_manager.cpp
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "foobar2000.h"
|
||||
|
||||
#ifdef FOOBAR2000_HAVE_DSP
|
||||
|
||||
void dsp_manager::close() {
|
||||
m_chain.remove_all();
|
||||
m_config_changed = true;
|
||||
}
|
||||
|
||||
void dsp_manager::set_config( const dsp_chain_config & p_data )
|
||||
{
|
||||
//dsp_chain_config::g_instantiate(m_dsp_list,p_data);
|
||||
m_config.copy(p_data);
|
||||
m_config_changed = true;
|
||||
}
|
||||
|
||||
bool dsp_manager::need_track_change_mark() const {
|
||||
for ( auto i = this->m_chain.first(); i.is_valid(); ++ i ) {
|
||||
if ( i->m_dsp->need_track_change_mark() ) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
p_list->remove_bad_chunks();
|
||||
|
||||
TRACK_CODE("dsp::run",p_iter->m_dsp->run_abortable(p_list,cur_file,flags,p_abort));
|
||||
TRACK_CODE("dsp::get_latency",latency += p_iter->m_dsp->get_latency());
|
||||
}
|
||||
|
||||
double dsp_manager::run(dsp_chunk_list * p_list,const metadb_handle_ptr & p_cur_file,unsigned p_flags,abort_callback & p_abort) {
|
||||
TRACK_CALL_TEXT("dsp_manager::run");
|
||||
|
||||
try {
|
||||
#if defined(_MSC_VER) && defined(_M_IX86)
|
||||
fpu_control_default l_fpu_control;
|
||||
#endif
|
||||
double latency=0;
|
||||
bool done = false;
|
||||
|
||||
t_dsp_chain::const_iterator flush_mark;
|
||||
if ((p_flags & dsp::END_OF_TRACK) && ! (p_flags & dsp::FLUSH)) {
|
||||
for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
|
||||
if (iter->m_dsp->need_track_change_mark()) flush_mark = iter;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config_changed)
|
||||
{
|
||||
t_dsp_chain newchain;
|
||||
bool recycle_available = true;
|
||||
|
||||
for(t_size n=0;n<m_config.get_count();n++) {
|
||||
service_ptr_t<dsp> temp;
|
||||
|
||||
const dsp_preset & preset = m_config.get_item(n);
|
||||
const GUID owner = preset.get_owner();
|
||||
if (dsp_entry::g_dsp_exists(owner) || dsp_entry_hidden::g_dsp_exists(owner)) {
|
||||
t_dsp_chain::iterator iter = newchain.insert_last();
|
||||
iter->m_preset = m_config.get_item(n);
|
||||
iter->m_recycle_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Recycle existing DSPs in a special case when user has apparently only altered settings of one of DSPs.
|
||||
if (newchain.get_count() == m_chain.get_count()) {
|
||||
t_size data_mismatch_count = 0;
|
||||
t_size owner_mismatch_count = 0;
|
||||
t_dsp_chain::iterator iter_src, iter_dst;
|
||||
iter_src = m_chain.first(); iter_dst = newchain.first();
|
||||
while(iter_src.is_valid() && iter_dst.is_valid()) {
|
||||
if (iter_src->m_preset.get_owner() != iter_dst->m_preset.get_owner()) {
|
||||
owner_mismatch_count++;
|
||||
} else if (iter_src->m_preset != iter_dst->m_preset) {
|
||||
data_mismatch_count++;
|
||||
}
|
||||
++iter_src; ++iter_dst;
|
||||
}
|
||||
recycle_available = (owner_mismatch_count == 0 && data_mismatch_count <= 1);
|
||||
} else {
|
||||
recycle_available = false;
|
||||
}
|
||||
|
||||
if (recycle_available) {
|
||||
t_dsp_chain::iterator iter_src, iter_dst;
|
||||
iter_src = m_chain.first(); iter_dst = newchain.first();
|
||||
while(iter_src.is_valid() && iter_dst.is_valid()) {
|
||||
if (iter_src->m_preset == iter_dst->m_preset) {
|
||||
iter_src->m_recycle_flag = true;
|
||||
iter_dst->m_dsp = iter_src->m_dsp;
|
||||
}
|
||||
++iter_src; ++iter_dst;
|
||||
}
|
||||
}
|
||||
|
||||
for(t_dsp_chain::iterator iter = newchain.first(); iter.is_valid(); ++iter) {
|
||||
if (iter->m_dsp.is_empty()) {
|
||||
if (!dsp_entry::g_instantiate(iter->m_dsp,iter->m_preset) && !dsp_entry_hidden::g_instantiate(iter->m_dsp, iter->m_preset)) uBugCheck();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_chain.get_count()>0) {
|
||||
bool flushflag = flush_mark.is_valid();
|
||||
for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
|
||||
unsigned flags2 = p_flags;
|
||||
if (iter == flush_mark) flushflag = false;
|
||||
if (flushflag || !iter->m_recycle_flag) flags2|=dsp::FLUSH;
|
||||
dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
m_chain = newchain;
|
||||
m_config_changed = false;
|
||||
}
|
||||
|
||||
if (!done)
|
||||
{
|
||||
bool flushflag = flush_mark.is_valid();
|
||||
for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
|
||||
unsigned flags2 = p_flags;
|
||||
if (iter == flush_mark) flushflag = false;
|
||||
if (flushflag) flags2|=dsp::FLUSH;
|
||||
dsp_run(iter,p_list,p_cur_file,flags2,latency,p_abort);
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
p_list->remove_bad_chunks();
|
||||
|
||||
return latency;
|
||||
} catch(...) {
|
||||
p_list->remove_all();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void dsp_manager::flush()
|
||||
{
|
||||
for(t_dsp_chain::const_iterator iter = m_chain.first(); iter.is_valid(); ++iter) {
|
||||
TRACK_CODE("dsp::flush",iter->m_dsp->flush());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool dsp_manager::is_active() const {return m_config.get_count()>0;}
|
||||
|
||||
void dsp_config_manager::core_enable_dsp(const dsp_preset & preset, default_insert_t insertWhere ) {
|
||||
dsp_chain_config_impl cfg;
|
||||
get_core_settings(cfg);
|
||||
|
||||
bool found = false;
|
||||
bool changed = false;
|
||||
t_size n,m = cfg.get_count();
|
||||
for(n=0;n<m;n++) {
|
||||
if (cfg.get_item(n).get_owner() == preset.get_owner()) {
|
||||
found = true;
|
||||
if (cfg.get_item(n) != preset) {
|
||||
cfg.replace_item(preset,n);
|
||||
changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if ( insertWhere == default_insert_last ) {
|
||||
cfg.add_item( preset );
|
||||
} else {
|
||||
cfg.insert_item(preset,0);
|
||||
}
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (changed) set_core_settings(cfg);
|
||||
}
|
||||
void dsp_config_manager::core_disable_dsp(const GUID & id) {
|
||||
dsp_chain_config_impl cfg;
|
||||
get_core_settings(cfg);
|
||||
|
||||
t_size n,m = cfg.get_count();
|
||||
pfc::bit_array_bittable mask(m);
|
||||
bool changed = false;
|
||||
for(n=0;n<m;n++) {
|
||||
bool axe = (cfg.get_item(n).get_owner() == id) ? true : false;
|
||||
if (axe) changed = true;
|
||||
mask.set(n,axe);
|
||||
}
|
||||
if (changed) {
|
||||
cfg.remove_mask(mask);
|
||||
set_core_settings(cfg);
|
||||
}
|
||||
}
|
||||
|
||||
bool dsp_config_manager::core_query_dsp(const GUID & id, dsp_preset & out) {
|
||||
dsp_chain_config_impl cfg;
|
||||
get_core_settings(cfg);
|
||||
for(t_size n=0;n<cfg.get_count();n++) {
|
||||
const dsp_preset & entry = cfg.get_item(n);
|
||||
if (entry.get_owner() == id) {
|
||||
out = entry; return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user