diff --git a/samplebrain/qt/MainWindow.cpp b/samplebrain/qt/MainWindow.cpp index ffc55d4..5a663ec 100644 --- a/samplebrain/qt/MainWindow.cpp +++ b/samplebrain/qt/MainWindow.cpp @@ -32,19 +32,21 @@ MainWindow::MainWindow() : setUnifiedTitleAndToolBarOnMac(true); m_sound_item_enable_mapper = new QSignalMapper(this); + m_sound_item_delete_mapper = new QSignalMapper(this); m_Ui.brain_contents->setAlignment(Qt::AlignTop); m_Ui.brain_contents->setSpacing(0); m_Ui.brain_contents->setMargin(0); m_Ui.brain_contents->setContentsMargins(0,0,0,0); connect(m_sound_item_enable_mapper, SIGNAL(mapped(int)), this, SLOT(sound_enable(int))); + connect(m_sound_item_delete_mapper, + SIGNAL(mapped(int)), this, SLOT(delete_sound(int))); m_current_sound_id=0; // add default local dest // turn on first one QSignalMapper* enable_mapper = new QSignalMapper(this); - QSignalMapper* connect_mapper = new QSignalMapper(this); for (int i=0; i<10; i++) { osc_destination d; @@ -53,7 +55,7 @@ MainWindow::MainWindow() : d.m_process_address = lo_address_new_from_url("osc.udp://localhost:8889"); if (i==0) d.m_enabled=true; else d.m_enabled=false; - add_gui_address(d,enable_mapper,connect_mapper); + add_gui_address(d,enable_mapper); if (i==0) { d.m_enable->setChecked(true); @@ -63,7 +65,6 @@ MainWindow::MainWindow() : } connect(enable_mapper, SIGNAL(mapped(int)), this, SLOT(net_enable(int))); - connect(connect_mapper, SIGNAL(mapped(int)), this, SLOT(net_connect(int))); m_Ui.netContainer->addItem(new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding)); @@ -77,8 +78,7 @@ MainWindow::MainWindow() : } void MainWindow::add_gui_address(osc_destination &dest, - QSignalMapper* enable_mapper, - QSignalMapper* connect_mapper) { + QSignalMapper* enable_mapper) { QHBoxLayout *h = new QHBoxLayout(); dest.m_enable = new QCheckBox(); dest.m_enable->setText("enable"); @@ -86,15 +86,10 @@ void MainWindow::add_gui_address(osc_destination &dest, h->addWidget(dest.m_enable); dest.m_address = new QLineEdit(); h->addWidget(dest.m_address); - //QPushButton *ping = new QPushButton(); - //ping->setText("connect"); - //h->addWidget(ping); m_Ui.netContainer->addLayout(h); QObject::connect(dest.m_enable, SIGNAL(clicked()), enable_mapper, SLOT(map())); enable_mapper->setMapping(dest.m_enable, dest.m_id); - //QObject::connect(ping, SIGNAL(clicked()), connect_mapper, SLOT(map())); - //connect_mapper->setMapping(ping, dest.m_id); } void MainWindow::init_from_session(const string &filename) { @@ -161,11 +156,9 @@ void MainWindow::init_from_session(const string &filename) { m_Ui.comboBoxBrainShape->setCurrentIndex(source_window); // brain samples - // m_Ui.listWidgetSounds->clear(); - const std::list samples = s.get_samples(); - for (std::list::const_iterator i=samples.begin(); - i!=samples.end(); ++i) { - add_sound_item(i->m_filename); + clear_sound_items(); + for (auto &i:s.get_samples()) { + add_sound_item(i.m_filename,i.m_enabled); } @@ -182,7 +175,7 @@ void MainWindow::init_from_session(const string &filename) { } -void MainWindow::add_sound_item(const string &name) { +void MainWindow::add_sound_item(const string &name, bool enabled) { sound_item si; si.m_filename = name; si.m_id = m_current_sound_id++; @@ -191,42 +184,69 @@ void MainWindow::add_sound_item(const string &name) { si.m_container = new QHBoxLayout(); si.m_enable = new QCheckBox(); - si.m_enable->setChecked(true); + si.m_enable->setChecked(enabled); si.m_enable->setStyleSheet(style); si.m_container->addWidget(si.m_enable); - QLabel *l = new QLabel(); - + si.m_label = new QLabel(); QFileInfo fi(QString::fromStdString(name)); - l->setText(fi.fileName()); - l->setStyleSheet(style); - si.m_container->addWidget(l); + si.m_label->setText(fi.fileName()); + si.m_label->setStyleSheet(style); + si.m_label->setSizePolicy(QSizePolicy::MinimumExpanding, + QSizePolicy::Minimum); + si.m_container->addWidget(si.m_label); - QSpacerItem *spacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); - //spacer->setStyleSheet(style); - si.m_container->addItem(spacer); - - QPushButton *del = new QPushButton(); - del->setText("x"); - del->setMaximumWidth(20); - del->setMaximumHeight(20); - si.m_container->addWidget(del); + si.m_del = new QPushButton(); + si.m_del->setText("x"); + si.m_del->setMaximumWidth(20); + si.m_del->setMaximumHeight(20); + si.m_del->setStyleSheet(style); + si.m_container->addWidget(si.m_del); m_Ui.brain_contents->addLayout(si.m_container); QObject::connect(si.m_enable, SIGNAL(clicked()), m_sound_item_enable_mapper, SLOT(map())); m_sound_item_enable_mapper->setMapping(si.m_enable, si.m_id); + QObject::connect(si.m_del, SIGNAL(clicked()), m_sound_item_delete_mapper, SLOT(map())); + m_sound_item_delete_mapper->setMapping(si.m_del, si.m_id); m_sound_items.push_back(si); } void MainWindow::clear_sound_items() { - for (auto si:m_sound_items) { + for (auto &si:m_sound_items) { + delete si.m_enable; + delete si.m_del; + delete si.m_label; delete si.m_container; } m_sound_items.clear(); } +void MainWindow::recolour_sound_items() { + u32 c=0; + for (auto &si:m_sound_items) { + QString style("background-color:lightblue;"); + if (c%2==0) style="background-color:pink;"; + si.m_enable->setStyleSheet(style); + si.m_del->setStyleSheet(style); + si.m_label->setStyleSheet(style); + c++; + } +} void MainWindow::delete_sound_item(const string &name) { + for (auto i=m_sound_items.begin(); i!=m_sound_items.end(); ++i) { + if (i->m_filename==name) { + // not sure why deleteLater-ing the container does not + // remove the children (like it does with delete) + i->m_container->deleteLater(); + i->m_enable->deleteLater(); + i->m_label->deleteLater(); + i->m_del->deleteLater(); + m_sound_items.erase(i); + recolour_sound_items(); + return; + } + } } diff --git a/samplebrain/qt/MainWindow.h b/samplebrain/qt/MainWindow.h index d840235..e120082 100644 --- a/samplebrain/qt/MainWindow.h +++ b/samplebrain/qt/MainWindow.h @@ -156,21 +156,40 @@ private slots: send_process_osc("/load_sample","s",m_last_file.toStdString().c_str()); - add_sound_item(m_last_file.toStdString()); - //m_Ui.listWidgetSounds->addItem(m_last_file); + add_sound_item(m_last_file.toStdString(),true); } - void delete_sound() { - //QList itemList = m_Ui.listWidgetSounds->selectedItems(); - //for (int i=0; itext().toStdString().c_str()); - //} - //qDeleteAll(m_Ui.listWidgetSounds->selectedItems()); + + void sound_enable(int id) { + // search for this id... + for (auto si:m_sound_items) { + if (si.m_id==id) { + if (si.m_enable->isChecked()) { + send_process_osc("/activate_sound","s",si.m_filename.c_str()); + } else { + send_process_osc("/deactivate_sound","s",si.m_filename.c_str()); + } + } + } + } + + void delete_sound(int id) { + // search for this id... + for (auto &si:m_sound_items) { + if (si.m_id==id) { + send_process_osc("/delete_sample","s",si.m_filename.c_str()); + delete_sound_item(si.m_filename); + // iterator is now invalidated... + return; + } + } } void clear_brain() { - //for (int i=0; icount(); i++) { - // send_process_osc("/delete_sample","s",m_Ui.listWidgetSounds->item(i)->text().toStdString().c_str()); - //} - //m_Ui.listWidgetSounds->clear(); + cerr<<"clear brain"<isChecked()) { - send_process_osc("/activate_sound","s",si.m_filename.c_str()); - } else { - send_process_osc("/deactivate_sound","s",si.m_filename.c_str()); - } - } - } - } private: @@ -296,14 +303,17 @@ private: string m_filename; // can't find a way to address these via qt QCheckBox *m_enable; + QPushButton *m_del; + QLabel *m_label; QHBoxLayout *m_container; }; vector m_sound_items; - void add_sound_item(const string &name); + void add_sound_item(const string &name, bool enabled); void delete_sound_item(const string &name); void clear_sound_items(); + void recolour_sound_items(); //////////////////////////////////////////////// @@ -361,8 +371,7 @@ private: void init_from_session(const string &filename); void add_gui_address(osc_destination &dest, - QSignalMapper* enable_mapper, - QSignalMapper* connect_mapper); + QSignalMapper* enable_mapper); string m_save_wav; QString m_last_file; @@ -372,4 +381,5 @@ private: int m_current_sound_id; QSignalMapper* m_sound_item_enable_mapper; + QSignalMapper* m_sound_item_delete_mapper; }; diff --git a/samplebrain/qt/process_thread.cpp b/samplebrain/qt/process_thread.cpp index 6749dd8..e00f944 100644 --- a/samplebrain/qt/process_thread.cpp +++ b/samplebrain/qt/process_thread.cpp @@ -68,14 +68,11 @@ void process_thread::process() { pthread_mutex_unlock(m_brain_mutex); } if (name=="/activate_sound") { - cerr<<"recieved activate"<::iterator i=m_sample_sections.begin(); - i!=m_sample_sections.end(); ++i) { + for (auto i=m_samples.begin(); i!=m_samples.end(); ++i) { if (filename==i->m_filename) { i->m_enabled=active; } @@ -97,7 +96,6 @@ void brain::clear() { m_blocks.clear(); m_samples.clear(); m_active_sounds.clear(); - m_sample_sections.clear(); } // rewrites whole brain @@ -108,18 +106,15 @@ void brain::init(u32 block_size, u32 overlap, window::type t, bool ditchpcm) { m_window.init(block_size); m_window.set_current_type(t); u32 count=0; - for (auto s : m_samples) { + for (auto s=m_samples.begin(); s!=m_samples.end(); ++s) { count++; - chop_and_add(s, count, ditchpcm); + chop_and_add(*s, count, ditchpcm); } status::update("all samples processed"); } void brain::chop_and_add(sound &s, u32 count, bool ditchpcm) { - sample_section ss; - ss.m_filename = s.m_filename; - ss.m_enabled = true; - ss.m_start = m_blocks.size(); + s.m_start = m_blocks.size(); u32 pos=0; if (m_overlap>=m_block_size) m_overlap=0; while (pos+m_block_size-1furthest) { furthest=diff; @@ -224,8 +213,8 @@ u32 brain::rev_search(const block &target, const search_params ¶ms) { // really slow - every to every comparison of blocks calculating average distance double brain::calc_average_diff(search_params ¶ms) { double diff=0; - for (auto i:m_blocks) { - for (auto j:m_blocks) { + for (auto &i:m_blocks) { + for (auto &j:m_blocks) { diff += j.compare(i,params); } diff/=(double)m_blocks.size(); @@ -238,15 +227,15 @@ void brain::build_synapses_thresh(search_params ¶ms, double thresh) { double err = m_average_error*thresh; u32 brain_size = m_blocks.size(); u32 outer_index = 0; - for (vector::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) { + for (auto &i : m_blocks) { u32 index = 0; status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); - for (vector::iterator j=m_blocks.begin(); j!=m_blocks.end(); ++j) { + for (auto &j : m_blocks) { if (index!=outer_index) { // collect connections that are under threshold in closeness - double diff = i->compare(*j,params); + double diff = i.compare(j,params); if (diffget_synapse().push_back(index); + i.get_synapse().push_back(index); } } ++index; @@ -262,16 +251,16 @@ void brain::build_synapses_fixed(search_params ¶ms) { u32 num_synapses = NUM_FIXED_SYNAPSES; if (num_synapses>=m_blocks.size()) num_synapses=m_blocks.size()-1; - for (vector::iterator i=m_blocks.begin(); i!=m_blocks.end(); ++i) { + for (auto &i:m_blocks) { status::update("building synapses %d%%",(int)(outer_index/(float)brain_size*100)); u32 index = 0; vector> collect; // collect comparisons to all other blocks - for (vector::iterator j=m_blocks.begin(); j!=m_blocks.end(); ++j) { + for (auto &j:m_blocks) { assert(indexcompare(*j,params); + double diff = i.compare(j,params); collect.push_back(pair(index,diff)); } ++index; @@ -287,7 +276,7 @@ void brain::build_synapses_fixed(search_params ¶ms) { // add the closest ones to the list for(u32 n=0; nget_synapse().push_back(collect[n].first); + i.get_synapse().push_back(collect[n].first); } ++outer_index; @@ -306,8 +295,8 @@ void brain::jiggle() { bool brain::is_block_active(u32 index) { // check each sample section - for (auto ss : m_sample_sections) { - if (index>=ss.m_start && index=s.m_start && index0) { - s||b.m_num_blocks; + s||b.m_num_blocks||b.m_start||b.m_end||b.m_enabled; } return s; } -ios &spiralcore::operator||(ios &s, brain::sample_section &b) { - u32 version=1; - string id("sample_section"); - s||id||version; - s||b.m_filename||b.m_enabled||b.m_start||b.m_end; - return s; -} - ios &spiralcore::operator||(ios &s, brain &b) { u32 version=1; string id("brain"); @@ -420,9 +401,6 @@ ios &spiralcore::operator||(ios &s, brain &b) { s||b.m_block_size||b.m_overlap||b.m_window; s||b.m_current_block_index||b.m_current_error|| b.m_average_error||b.m_usage_falloff; - if (version>0) { - stream_vector(s,b.m_sample_sections); - } return s; } diff --git a/samplebrain/src/brain.h b/samplebrain/src/brain.h index cf9db8a..8f37a0a 100644 --- a/samplebrain/src/brain.h +++ b/samplebrain/src/brain.h @@ -75,12 +75,20 @@ public: class sound { public: sound(const std::string &name, const sample &sample) : - m_filename(name), m_sample(sample), m_num_blocks(0) {} + m_filename(name), m_sample(sample), m_num_blocks(0), + m_enabled(true), m_start(0), m_end(0) {} sound() {}; // needed for streaming std::string m_filename; sample m_sample; // filled in during chop_and_add u32 m_num_blocks; + bool m_enabled; + // we store the blocks separately in a flat list, so we can + // directly index them, but we need to filter them by source + // sound - so we need to be able to turn large contiguous sets + // of them on and off (without a big impact on the processing + // time) + u32 m_start,m_end; }; const std::list &get_samples() { return m_samples; } @@ -94,22 +102,9 @@ private: // checks sample sections bool is_block_active(u32 index); - // we store the blocks in a flat list, so we can directly index - // them, but we need to filter them by source sound - so we need - // to be able to turn large contiguous sets of them on and off - // (without a big impact on the processing time) - class sample_section { - public: - std::string m_filename; - bool m_enabled; - u32 m_start,m_end; - }; - vector m_blocks; std::list m_samples; vector m_active_sounds; - vector m_sample_sections; - u32 m_block_size; u32 m_overlap; @@ -122,13 +117,11 @@ private: float m_usage_falloff; friend ios &operator||(ios &s, brain &b); - friend ios &operator||(ios &s, sample_section &b); friend ios &operator||(ios &s, sound &b); }; ios &operator||(ios &s, brain::sound &b); -ios &operator||(ios &s, brain::sample_section &b); ios &operator||(ios &s, brain &b); }