implement view switching from world tree
[ladish.git] / gui / main.c
blob0a3fd32ff83d69d42a07c8573b8bcd54fe45a70d
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2007 Dave Robillard <http://drobilla.net>
8 **************************************************************************
9 * This file contains the code that implements main() and other top-level functionality
10 **************************************************************************
12 * LADI Session Handler is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * LADI Session Handler is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
24 * or write to the Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "common.h"
29 #include "glade.h"
30 #include "canvas.h"
31 #include "graph_canvas.h"
32 #include "../jack_proxy.h"
33 #include "dbus_helpers.h"
34 #include "control_proxy.h"
35 #include "../dbus_constants.h"
36 #include "world_tree.h"
37 #include "graph_view.h"
39 #if 0
40 class Patchage {
41 public:
42 Patchage();
43 ~Patchage();
45 Gtk::Window* window() { return _main_win.get(); }
47 void quit() { _main_win->hide(); }
49 void refresh();
51 void clear_load();
52 void update_state();
54 void set_studio_availability(bool available);
55 #if 0
56 void set_a2j_status(unsigned int status);
58 void load_project_ask();
59 void load_project(const std::string& project_name);
60 void save_all_projects();
61 void save_project(const std::string& project_name);
62 void close_project(const std::string& project_name);
63 void close_all_projects();
64 #endif
66 protected:
67 void connect_widgets();
69 void on_arrange();
70 void on_help_about();
71 void on_quit();
72 void on_show_projects();
73 void on_view_toolbar();
74 bool on_scroll(GdkEventScroll* ev);
76 void zoom(double z);
77 bool idle_callback();
78 void update_load();
79 void update_toolbar();
81 void jack_status_changed(bool started);
83 void buffer_size_changed();
85 #if 0
86 void
87 get_port_jack_names(
88 boost::shared_ptr<PatchagePort> port,
89 std::string& jack_client_name,
90 std::string& jack_port_name);
92 boost::shared_ptr<PatchagePort>
93 lookup_port(
94 const char * jack_client_name,
95 const char * jack_port_name);
96 #endif
98 //a2j_proxy * _a2j;
99 //session * _session;
100 //lash_proxy * _lash;
101 //project_list * _project_list;
103 Gtk::Main* _gtk_main;
105 float _max_dsp_load;
107 Widget<Gtk::AboutDialog> _about_win;
108 Widget<Gtk::ComboBox> _buffer_size_combo;
109 Widget<Gtk::ToolButton> _clear_load_but;
110 Widget<Gtk::ScrolledWindow> _main_scrolledwin;
111 Widget<Gtk::Window> _main_win;
112 Widget<Gtk::ProgressBar> _main_xrun_progress;
113 Widget<Gtk::Label> _main_a2j_status_label;
114 Widget<Gtk::MenuItem> _menu_file_quit;
115 Widget<Gtk::MenuItem> _menu_help_about;
116 Widget<Gtk::MenuItem> _menu_jack_start;
117 Widget<Gtk::MenuItem> _menu_jack_stop;
118 Widget<Gtk::MenuItem> _menu_a2j_start;
119 Widget<Gtk::MenuItem> _menu_a2j_stop;
120 Widget<Gtk::MenuItem> _menu_load_project;
121 Widget<Gtk::MenuItem> _menu_save_all_projects;
122 Widget<Gtk::MenuItem> _menu_close_all_projects;
123 Widget<Gtk::MenuItem> _menu_store_positions;
124 Widget<Gtk::MenuItem> _menu_view_arrange;
125 Widget<Gtk::CheckMenuItem> _menu_view_projects;
126 Widget<Gtk::MenuItem> _menu_view_refresh;
127 Widget<Gtk::CheckMenuItem> _menu_view_toolbar;
128 Widget<Gtk::Viewport> _project_list_viewport;
129 Widget<Gtk::Label> _sample_rate_label;
130 Widget<Gtk::Toolbar> _toolbar;
131 Widget<Gtk::ToolButton> _zoom_full_but;
132 Widget<Gtk::ToolButton> _zoom_normal_but;
135 #include "globals.hpp"
137 #include "common.h"
138 #include "Widget.hpp"
139 #include <gtkmm.h>
141 #include "common.h"
143 #include <string.h>
144 #include <cmath>
145 #include <libgnomecanvasmm.h>
146 #include <libglademm/xml.h>
147 #include <gtk/gtkwindow.h>
148 #include <boost/format.hpp>
150 #include "project_list.hpp"
151 #include "session.hpp"
152 #include "globals.hpp"
153 //#include "load_projects_dialog.hpp"
154 #include "graph_canvas.h"
155 #include "../jack_proxy.h"
157 Patchage * g_app;
159 #define LOG_TO_STD
160 //#define LOG_TO_STATUS
162 /* Gtk helpers (resize combo boxes) */
164 static void
165 gtkmm_get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
166 int& width,
167 int& height)
169 Pango::Rectangle ink_rect = layout->get_ink_extents ();
171 width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE;
172 height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE;
175 static void
176 gtkmm_set_width_for_given_text (Gtk::Widget &w, const gchar *text,
177 gint hpadding/*, gint vpadding*/)
180 int old_width, old_height;
181 w.get_size_request(old_width, old_height);
183 int width, height;
184 w.ensure_style ();
186 gtkmm_get_ink_pixel_size (w.create_pango_layout (text), width, height);
187 w.set_size_request(width + hpadding, old_height);//height + vpadding);
190 /* end Gtk helpers */
193 #define INIT_WIDGET(x) x(g_xml, ((const char*)#x) + 1)
195 Patchage::Patchage()
196 : _max_dsp_load(0.0)
197 #if 0
198 , INIT_WIDGET(_about_win)
199 , INIT_WIDGET(_buffer_size_combo)
200 , INIT_WIDGET(_clear_load_but)
201 , INIT_WIDGET(_main_scrolledwin)
202 , INIT_WIDGET(_main_win)
203 , INIT_WIDGET(_main_xrun_progress)
204 , INIT_WIDGET(_main_a2j_status_label)
205 , INIT_WIDGET(_menu_file_quit)
206 , INIT_WIDGET(_menu_help_about)
207 , INIT_WIDGET(_menu_jack_start)
208 , INIT_WIDGET(_menu_jack_stop)
209 , INIT_WIDGET(_menu_a2j_start)
210 , INIT_WIDGET(_menu_a2j_stop)
211 , INIT_WIDGET(_menu_load_project)
212 , INIT_WIDGET(_menu_save_all_projects)
213 , INIT_WIDGET(_menu_close_all_projects)
214 , INIT_WIDGET(_menu_store_positions)
215 , INIT_WIDGET(_menu_view_arrange)
216 , INIT_WIDGET(_menu_view_projects)
217 , INIT_WIDGET(_menu_view_refresh)
218 , INIT_WIDGET(_menu_view_toolbar)
219 , INIT_WIDGET(_project_list_viewport)
220 , INIT_WIDGET(_sample_rate_label)
221 , INIT_WIDGET(_toolbar)
222 , INIT_WIDGET(_zoom_full_but)
223 , INIT_WIDGET(_zoom_normal_but)
224 #endif
226 g_app = this;
228 patchage_dbus_init();
230 graph_create(JACKDBUS_SERVICE, JACKDBUS_OBJECT, &g_jack_graph);
231 graph_canvas_create(1600 * 2, 1200 * 2, &g_jack_graph_canvas);
232 graph_canvas_attach(g_jack_graph_canvas, g_jack_graph);
233 graph_activate(g_jack_graph);
235 Glib::set_application_name("Patchage");
236 _about_win->property_program_name() = "Patchage";
237 _about_win->property_logo_icon_name() = "gladish";
238 gtk_window_set_default_icon_name("gladish");
240 gtkmm_set_width_for_given_text(*_buffer_size_combo, "4096 frames", 40);
242 _main_scrolledwin->add(*Glib::wrap(canvas_get_widget(graph_canvas_get_canvas(g_jack_graph_canvas))));
244 // _canvas->scroll_to(static_cast<int>(_canvas->width()/2 - 320),
245 // static_cast<int>(_canvas->height()/2 - 240)); // FIXME: hardcoded
247 _main_scrolledwin->property_hadjustment().get_value()->set_step_increment(10);
248 _main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10);
250 _main_scrolledwin->signal_scroll_event().connect(
251 sigc::mem_fun(this, &Patchage::on_scroll));
253 _buffer_size_combo->signal_changed().connect(
254 sigc::mem_fun(this, &Patchage::buffer_size_changed));
255 _clear_load_but->signal_clicked().connect(
256 sigc::mem_fun(this, &Patchage::clear_load));
257 _zoom_normal_but->signal_clicked().connect(sigc::bind(
258 sigc::mem_fun(this, &Patchage::zoom), 1.0));
259 // _zoom_full_but->signal_clicked().connect(sigc::mem_fun(_canvas.get(), &PatchageCanvas::zoom_full));
261 // _menu_load_project->signal_activate().connect(sigc::mem_fun(this, &Patchage::load_project_ask));
262 // _menu_save_all_projects->signal_activate().connect(sigc::mem_fun(this, &Patchage::save_all_projects));
263 // _menu_close_all_projects->signal_activate().connect(sigc::mem_fun(this, &Patchage::close_all_projects));
265 _menu_file_quit->signal_activate().connect(
266 sigc::mem_fun(this, &Patchage::on_quit));
267 _menu_view_refresh->signal_activate().connect(
268 sigc::mem_fun(this, &Patchage::refresh));
269 _menu_view_arrange->signal_activate().connect(
270 sigc::mem_fun(this, &Patchage::on_arrange));
271 _menu_view_toolbar->signal_activate().connect(
272 sigc::mem_fun(this, &Patchage::on_view_toolbar));
273 _menu_view_projects->signal_toggled().connect(
274 sigc::mem_fun(this, &Patchage::on_show_projects));
275 _menu_help_about->signal_activate().connect(
276 sigc::mem_fun(this, &Patchage::on_help_about));
278 Glib::wrap(canvas_get_widget(graph_canvas_get_canvas(g_jack_graph_canvas)))->show();
279 _main_win->present();
281 _about_win->set_transient_for(*_main_win);
283 // _a2j = new a2j_proxy;
285 //info_msg(str(boost::format("a2j jack client name is '%s'") % _a2j->get_jack_client_name()));
287 // _session = new session();
289 // _project_list = new project_list(this, _session);
290 // _project_list_viewport->hide();
292 // _lash = new lash_proxy(_session);
294 //_menu_jack_start->signal_activate().connect(sigc::mem_fun(_jack, &jack_proxy::start_server));
295 //_menu_jack_stop->signal_activate().connect(sigc::mem_fun(_jack, &jack_proxy::stop_server));
297 // _menu_a2j_start->signal_activate().connect(sigc::mem_fun(_a2j, &a2j_proxy::start_bridge));
298 // _menu_a2j_stop->signal_activate().connect(sigc::mem_fun(_a2j, &a2j_proxy::stop_bridge));
300 //jack_status_changed(_jack->is_started());
302 connect_widgets();
303 update_state();
305 // _canvas->grab_focus();
307 // Idle callback, check if we need to refresh
308 Glib::signal_timeout().connect(
309 sigc::mem_fun(this, &Patchage::idle_callback), 100);
312 Patchage::~Patchage()
314 //delete _lash;
315 //delete _project_list;
316 //delete _session;
317 //delete _a2j;
319 _about_win.destroy();
320 //_main_win.destroy();
322 patchage_dbus_uninit();
325 bool
326 Patchage::idle_callback()
328 update_load();
330 return true;
333 void
334 Patchage::update_toolbar()
336 #if 0
337 bool started;
339 started = _jack->is_started();
341 _buffer_size_combo->set_sensitive(started);
343 if (started)
345 _buffer_size_combo->set_active((int)log2f(_jack->buffer_size()) - 5);
347 #endif
350 void
351 Patchage::update_load()
353 #if 0
354 if (!_jack->is_started())
356 _main_xrun_progress->set_text("JACK stopped");
357 return;
360 char tmp_buf[8];
361 snprintf(tmp_buf, 8, "%zd", _jack->xruns());
363 _main_xrun_progress->set_text(std::string(tmp_buf) + " Dropouts");
365 float load = _jack->get_dsp_load();
367 load /= 100.0; // dbus returns it in percents, we use 0..1
369 if (load > _max_dsp_load)
371 _max_dsp_load = load;
372 _main_xrun_progress->set_fraction(load);
374 #endif
378 void
379 Patchage::zoom(double z)
381 // _canvas->set_zoom(z);
385 void
386 Patchage::refresh()
388 // assert(_canvas);
390 // _canvas->destroy();
392 // if (_jack)
393 // _jack->refresh();
395 // for (ItemList::iterator i = _canvas->items().begin(); i != _canvas->items().end(); ++i) {
396 // (*i)->resize();
397 // }
400 void
401 Patchage::clear_load()
403 #if 0
404 _main_xrun_progress->set_fraction(0.0);
405 _jack->reset_xruns();
406 _max_dsp_load = 0.0;
407 #endif
410 void
411 Patchage::update_state()
413 // for (ItemList::iterator i = _canvas->items().begin(); i != _canvas->items().end(); ++i) {
414 // shared_ptr<Module> module = dynamic_pointer_cast<Module>(*i);
415 // if (module)
416 // module->load_location();
417 // }
421 /** Update the sensitivity status of menus to reflect the present.
423 * (eg. disable "Connect to Jack" when Patchage is already connected to Jack)
425 void
426 Patchage::connect_widgets()
428 //_jack->signal_started.connect(sigc::bind(sigc::mem_fun(this, &Patchage::jack_status_changed), true));
429 //_jack->signal_stopped.connect(sigc::bind(sigc::mem_fun(this, &Patchage::jack_status_changed), false));
432 void
433 Patchage::jack_status_changed(
434 bool started)
436 update_toolbar();
438 _menu_jack_start->set_sensitive(!started);
439 _menu_jack_stop->set_sensitive(started);
440 _clear_load_but->set_sensitive(started);
441 if (!started)
443 _main_xrun_progress->set_fraction(0.0);
447 void
448 Patchage::on_arrange()
450 // assert(_canvas);
452 // _canvas->arrange();
456 void
457 Patchage::on_help_about()
459 _about_win->run();
460 _about_win->hide();
464 void
465 Patchage::on_quit()
467 _main_win->hide();
470 void
471 Patchage::on_show_projects()
473 if (_menu_view_projects->get_active())
474 _project_list_viewport->show();
475 else
476 _project_list_viewport->hide();
479 void
480 Patchage::on_view_toolbar()
482 if (_menu_view_toolbar->get_active())
483 _toolbar->show();
484 else
485 _toolbar->hide();
489 bool
490 Patchage::on_scroll(GdkEventScroll* ev)
492 lash_debug("ON SCROLL");
493 return false;
497 void
498 Patchage::buffer_size_changed()
500 #if 0
501 const int selected = _buffer_size_combo->get_active_row_number();
503 if (selected == -1)
505 update_toolbar();
507 else
509 uint32_t buffer_size = 1 << (selected+5);
511 // this check is temporal workaround for jack bug
512 // we skip setting buffer size if it same as acutal one
513 // proper place for such check is in jack
514 if (_jack->buffer_size() != buffer_size)
516 if (!_jack->set_buffer_size(buffer_size))
518 update_toolbar(); // reset combo box to actual value
522 #endif
525 void
526 Patchage::set_studio_availability(
527 bool available)
529 if (available)
531 _main_win->set_title("Active Studio - LADI Session Handler");
533 else
535 _main_win->set_title("LADI Session Handler");
537 //_project_list->set_lash_availability(available);
538 _menu_view_projects->set_active(available);
541 #if 0
542 void
543 Patchage::set_a2j_status(
544 unsigned int status)
546 const char * status_text;
548 switch (status)
550 case A2J_STATUS_NO_RESPONSE:
551 status_text = "A2J N/A";
552 _menu_a2j_start->set_sensitive(false);
553 _menu_a2j_stop->set_sensitive(false);
554 break;
555 case A2J_STATUS_BRIDGE_STOPPED:
556 status_text = "A2J bridge stopped";
557 _menu_a2j_start->set_sensitive(true);
558 _menu_a2j_stop->set_sensitive(false);
559 break;
560 case A2J_STATUS_BRIDGE_STARTED:
561 status_text = "A2J bridge started";
562 _menu_a2j_start->set_sensitive(false);
563 _menu_a2j_stop->set_sensitive(true);
564 break;
565 default:
566 error_msg(str(boost::format("Unknown A2J status %u") % status));
567 status_text = "Unknown A2J status";
568 _menu_a2j_start->set_sensitive(true);
569 _menu_a2j_stop->set_sensitive(true);
570 break;
573 _main_a2j_status_label->set_text(status_text);
576 void
577 Patchage::load_project_ask()
579 std::list<lash_project_info> projects;
581 _lash->get_available_projects(projects);
582 run_load_project_dialog(projects);
585 void
586 Patchage::load_project(
587 const std::string& project_name)
589 _lash->load_project(project_name);
592 void
593 Patchage::save_all_projects()
595 _lash->save_all_projects();
598 void
599 Patchage::save_project(
600 const std::string& project_name)
602 _lash->save_project(project_name);
605 void
606 Patchage::close_project(
607 const std::string& project_name)
609 _lash->close_project(project_name);
612 void
613 Patchage::close_all_projects()
615 _lash->close_all_projects();
618 void
619 Patchage::on_port_added(
620 const char * jack_client_name,
621 const char * jack_port_name,
622 PortType port_type,
623 bool is_input,
624 bool is_terminal)
626 bool is_a2j_mapped;
627 std::string canvas_client_name;
628 std::string canvas_port_name;
629 uint32_t alsa_client_id;
630 boost::shared_ptr<PatchageModule> module;
632 is_a2j_mapped = strcmp(_a2j->get_jack_client_name(), jack_client_name) == 0;
633 if (is_a2j_mapped)
635 if (!_a2j->map_jack_port(jack_port_name, canvas_client_name, canvas_port_name, alsa_client_id))
637 return;
640 canvas_port_name = str(boost::format(canvas_port_name + " [a2j:%u]") % alsa_client_id);
642 else
644 canvas_client_name = jack_client_name;
645 canvas_port_name = jack_port_name;
648 ModuleType module_type = InputOutput;
649 if (_state_manager->get_module_split(canvas_client_name, is_terminal && !is_a2j_mapped)) {
650 if (is_input) {
651 module_type = Input;
652 } else {
653 module_type = Output;
657 module = _canvas->find_module(canvas_client_name, module_type);
658 if (!module) {
659 module = boost::shared_ptr<PatchageModule>(new PatchageModule(this, canvas_client_name, module_type));
660 module->load_location();
661 _canvas->add_item(module);
664 if (module->get_port(canvas_port_name)) {
665 return;
668 boost::shared_ptr<PatchagePort> port = boost::shared_ptr<PatchagePort>(
669 new PatchagePort(
670 module,
671 canvas_port_name,
672 is_input,
673 _state_manager->get_port_color(port_type)));
675 port->type = port_type;
676 port->is_a2j_mapped = is_a2j_mapped;
677 if (is_a2j_mapped)
679 port->a2j_jack_port_name = jack_port_name;
682 module->add_port(port);
684 module->resize();
687 boost::shared_ptr<PatchagePort>
688 Patchage::lookup_port(
689 const char * jack_client_name,
690 const char * jack_port_name)
692 if (strcmp(_a2j->get_jack_client_name(), jack_client_name) == 0)
694 return _canvas->lookup_port_by_a2j_jack_port_name(jack_port_name);
697 return _canvas->get_port(jack_client_name, jack_port_name);
700 void
701 Patchage::on_port_removed(
702 const char * jack_client_name,
703 const char * jack_port_name)
705 boost::shared_ptr<PatchagePort> port = lookup_port(jack_client_name, jack_port_name);
706 if (!port) {
707 error_msg(str(boost::format("Unable to remove unknown port '%s':'%s'") % jack_client_name % jack_port_name));
708 return;
711 boost::shared_ptr<PatchageModule> module = dynamic_pointer_cast<PatchageModule>(port->module().lock());
713 module->remove_port(port);
714 port.reset();
716 // No empty modules (for now)
717 if (module->num_ports() == 0) {
718 _canvas->remove_item(module);
719 module.reset();
720 } else {
721 module->resize();
725 void
726 Patchage::on_ports_connected(
727 const char * jack_client1_name,
728 const char * jack_port1_name,
729 const char * jack_client2_name,
730 const char * jack_port2_name)
732 boost::shared_ptr<PatchagePort> port1 = lookup_port(jack_client1_name, jack_port1_name);
733 if (!port1) {
734 error_msg((std::string)"Unable to connect unknown port '" + jack_port1_name + "' of client '" + jack_client1_name + "'");
735 return;
738 boost::shared_ptr<PatchagePort> port2 = lookup_port(jack_client2_name, jack_port2_name);
739 if (!port2) {
740 error_msg((std::string)"Unable to connect unknown port '" + jack_port2_name + "' of client '" + jack_client2_name + "'");
741 return;
744 _canvas->add_connection(port1, port2, port1->color() + 0x22222200);
747 void
748 Patchage::on_ports_disconnected(
749 const char * jack_client1_name,
750 const char * jack_port1_name,
751 const char * jack_client2_name,
752 const char * jack_port2_name)
754 boost::shared_ptr<PatchagePort> port1 = lookup_port(jack_client1_name, jack_port1_name);
755 if (!port1) {
756 error_msg((std::string)"Unable to disconnect unknown port '" + jack_port1_name + "' of client '" + jack_client1_name + "'");
757 return;
760 boost::shared_ptr<PatchagePort> port2 = lookup_port(jack_client2_name, jack_port2_name);
761 if (!port2) {
762 error_msg((std::string)"Unable to disconnect unknown port '" + jack_port2_name + "' of client '" + jack_client2_name + "'");
763 return;
766 _canvas->remove_connection(port1, port2);
769 static
770 bool
771 port_type_match(
772 boost::shared_ptr<PatchagePort> port1,
773 boost::shared_ptr<PatchagePort> port2)
775 return port1->type == port2->type;
778 void
779 Patchage::get_port_jack_names(
780 boost::shared_ptr<PatchagePort> port,
781 std::string& jack_client_name,
782 std::string& jack_port_name)
784 if (port->is_a2j_mapped)
786 jack_client_name = _a2j->get_jack_client_name();
787 jack_port_name = port->a2j_jack_port_name;
789 else
791 jack_client_name = port->module().lock()->name();
792 jack_port_name = port->name();
796 void
797 Patchage::connect(
798 boost::shared_ptr<PatchagePort> port1,
799 boost::shared_ptr<PatchagePort> port2)
801 std::string jack_client1_name;
802 std::string jack_port1_name;
803 std::string jack_client2_name;
804 std::string jack_port2_name;
806 if (port_type_match(port1, port2))
808 get_port_jack_names(port1, jack_client1_name, jack_port1_name);
809 get_port_jack_names(port2, jack_client2_name, jack_port2_name);
811 _jack->connect(
812 jack_client1_name.c_str(),
813 jack_port1_name.c_str(),
814 jack_client2_name.c_str(),
815 jack_port2_name.c_str());
817 else
819 status_msg("ERROR: Attempt to connect ports with mismatched types");
823 void
824 Patchage::disconnect(
825 boost::shared_ptr<PatchagePort> port1,
826 boost::shared_ptr<PatchagePort> port2)
828 std::string jack_client1_name;
829 std::string jack_port1_name;
830 std::string jack_client2_name;
831 std::string jack_port2_name;
833 if (port_type_match(port1, port2))
835 get_port_jack_names(port1, jack_client1_name, jack_port1_name);
836 get_port_jack_names(port2, jack_client2_name, jack_port2_name);
838 _jack->disconnect(
839 jack_client1_name.c_str(),
840 jack_port1_name.c_str(),
841 jack_client2_name.c_str(),
842 jack_port2_name.c_str());
844 else
846 status_msg("ERROR: Attempt to disconnect ports with mismatched types");
850 bool
851 Patchage::is_canvas_empty()
853 return _canvas->items().empty();
855 #endif
856 #endif
858 graph_view_handle g_jack_view = NULL;
859 graph_view_handle g_studio_view = NULL;
861 void control_proxy_on_studio_appeared(void)
863 if (!create_view("Studio", SERVICE_NAME, STUDIO_OBJECT_PATH, false, &g_studio_view))
865 lash_error("create_view() failed for studio");
866 return;
870 void control_proxy_on_studio_disappeared(void)
872 if (g_studio_view != NULL)
874 destroy_view(g_studio_view);
875 g_jack_view = NULL;
879 void jack_started(void)
881 lash_info("JACK started");
884 void jack_stopped(void)
886 lash_info("JACK stopped");
889 void jack_appeared(void)
891 lash_info("JACK appeared");
893 if (!create_view("Raw JACK", JACKDBUS_SERVICE_NAME, JACKDBUS_OBJECT_PATH, true, &g_jack_view))
895 lash_error("create_view() failed for jack");
896 return;
900 void jack_disappeared(void)
902 lash_info("JACK disappeared");
904 if (g_jack_view != NULL)
906 destroy_view(g_jack_view);
907 g_jack_view = NULL;
911 int main(int argc, char** argv)
913 GtkWidget * main_win;
915 gtk_init(&argc, &argv);
917 if (!canvas_init())
919 lash_error("Canvas initialization failed.");
920 return 1;
923 if (!init_glade())
925 return 1;
928 /* Obtain widgets that we need */
929 main_win = get_glade_widget("main_win");
931 world_tree_init();
932 view_init();
934 patchage_dbus_init();
936 if (!jack_proxy_init(jack_started, jack_stopped, jack_appeared, jack_disappeared))
938 return 1;
941 if (!control_proxy_init())
943 return 1;
946 //gtkmm_set_width_for_given_text(*_buffer_size_combo, "4096 frames", 40);
948 g_signal_connect(G_OBJECT(main_win), "destroy", G_CALLBACK(gtk_main_quit), NULL);
949 g_signal_connect(G_OBJECT(get_glade_widget("menu_file_quit")), "activate", G_CALLBACK(gtk_main_quit), NULL);
951 gtk_widget_show(main_win);
953 //_about_win->set_transient_for(*_main_win);
955 gtk_main();
957 control_proxy_uninit();
958 uninit_glade();
960 return 0;