#ifndef XTC_TRACK_INSERTS_HPP #define XTC_TRACK_INSERTS_HPP #include "main_window.hpp" #include "graph_widget.hpp" #include "plugin_library.hpp" #include "plugin_dialog.hpp" #include "sequencer_widget.hpp" #include #include #include #include #include #include class TrackInsertsPanel : public Fl_Group { MainWindow *owner_; Fl_Choice *tracks_; Fl_Hold_Browser *slots_; Fl_Box *message_; GraphWidget *graph_; xtc_graph *model_=nullptr; uint64_t track_=UINT64_MAX; xtc_track_chain cached_{}; std::vector ids_; void result(xtc_result r) { if(r!=XTC_OK)owner_->report_error("Track inserts",r);refresh(true); } public: TrackInsertsPanel(int x,int y,int w,int h,MainWindow *owner):Fl_Group(x,y,w,h,"Track inserts"),owner_(owner) { tracks_=new Fl_Choice(x+64,y+12,240,28,"Track");tracks_->callback([](Fl_Widget *,void *c){auto *p=static_cast(c);int i=p->tracks_->value();if(i>=0 && static_cast(i)ids_.size()){p->track_=p->ids_[static_cast(i)];p->refresh(true);}},this); auto *add=new Fl_Menu_Button(x+320,y+12,150,28,"Add effect"); add->add("Internal Delay",0,[](Fl_Widget *,void *c){static_cast(c)->add(XTC_BUILTIN_PATH,2);},this); add->add("Internal Reverb",0,[](Fl_Widget *,void *c){static_cast(c)->add(XTC_BUILTIN_PATH,3);},this); add->add("Plugin library...",0,[](Fl_Widget *,void *c){auto *p=static_cast(c);std::string file;if(!xtc_choose_plugin_file(p->owner_->settings(),file))return;unsigned int index=0;if(xtc_choose_plugin(file.c_str(),p->owner_->sample_rate(),index))p->add(file.c_str(),index);},this); message_=new Fl_Box(x+16,y+50,w-32,32,"Track input > inserts > output gain > track fader > bus/master");message_->align(FL_ALIGN_LEFT|FL_ALIGN_INSIDE); slots_=new Fl_Hold_Browser(x+16,y+94,230,h-110);slots_->format_char(0); graph_=new GraphWidget(x+260,y+94,w-276,h-110,nullptr,[](void *,const xtc_graph_edit &,size_t *){return XTC_ERR_UNSUPPORTED;},nullptr,message_); resizable(graph_);end(); } ~TrackInsertsPanel() override { graph_->set_graph(nullptr);xtc_graph_destroy(model_); } uint64_t selected_track() const {return track_;} size_t selected_slot() const {return slots_->value()>0 ? static_cast(slots_->value()-1) : SIZE_MAX;} void select_track(uint64_t id) {track_=id;refresh(true);} const xtc_graph *graph() const {return model_;} void add(const char *file,unsigned int index) { result(owner_->add_track_effect(track_,file,index)); } void refresh(bool force=false) { const xtc_project *project=owner_->project_.get();size_t count=0,clips=0;xtc_project_get_counts(project,&count,&clips); std::vector ids;std::vector names; for(size_t i=0;iclear();for(const auto &name:names) {tracks_->add("track");tracks_->replace(tracks_->size()-2,name.c_str());}} if(std::find(ids_.begin(),ids_.end(),track_)==ids_.end())track_=ids_.empty() ? UINT64_MAX : ids_[0]; for(size_t i=0;ivalue(static_cast(i)); xtc_track_chain chain{};chain.output_gain=1; if(track_!=UINT64_MAX)xtc_project_get_chain(project,track_,&chain); if(!rebuild && !std::memcmp(&cached_,&chain,sizeof(chain)))return; cached_=chain;int selected=slots_->value();slots_->clear(); for(size_t i=0;iadd(label.c_str());} if(chain.count)slots_->select(selected>0 && static_cast(selected)<=chain.count ? selected : 1); xtc_graph *next=nullptr;auto r=xtc_track_chain_graph(&chain,&next); if(r==XTC_OK){graph_->set_graph(next);xtc_graph_destroy(model_);model_=next;graph_->auto_layout();} redraw(); } }; #endif