Quit when requested from the menu
[ladish.git] / gui / main.c
bloba19c2c93b79766be2f5063b6e25cdb0b95ff4296
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"
35 #if 0
36 class Patchage {
37 public:
38 Patchage();
39 ~Patchage();
41 Gtk::Window* window() { return _main_win.get(); }
43 void quit() { _main_win->hide(); }
45 void refresh();
47 void clear_load();
48 void update_state();
50 void set_studio_availability(bool available);
51 #if 0
52 void set_a2j_status(unsigned int status);
54 void load_project_ask();
55 void load_project(const std::string& project_name);
56 void save_all_projects();
57 void save_project(const std::string& project_name);
58 void close_project(const std::string& project_name);
59 void close_all_projects();
60 #endif
62 protected:
63 void connect_widgets();
65 void on_arrange();
66 void on_help_about();
67 void on_quit();
68 void on_show_projects();
69 void on_view_toolbar();
70 bool on_scroll(GdkEventScroll* ev);
72 void zoom(double z);
73 bool idle_callback();
74 void update_load();
75 void update_toolbar();
77 void jack_status_changed(bool started);
79 void buffer_size_changed();
81 #if 0
82 void
83 get_port_jack_names(
84 boost::shared_ptr<PatchagePort> port,
85 std::string& jack_client_name,
86 std::string& jack_port_name);
88 boost::shared_ptr<PatchagePort>
89 lookup_port(
90 const char * jack_client_name,
91 const char * jack_port_name);
92 #endif
94 //a2j_proxy * _a2j;
95 //session * _session;
96 //lash_proxy * _lash;
97 //project_list * _project_list;
99 Gtk::Main* _gtk_main;
101 float _max_dsp_load;
103 Widget<Gtk::AboutDialog> _about_win;
104 Widget<Gtk::ComboBox> _buffer_size_combo;
105 Widget<Gtk::ToolButton> _clear_load_but;
106 Widget<Gtk::ScrolledWindow> _main_scrolledwin;
107 Widget<Gtk::Window> _main_win;
108 Widget<Gtk::ProgressBar> _main_xrun_progress;
109 Widget<Gtk::Label> _main_a2j_status_label;
110 Widget<Gtk::MenuItem> _menu_file_quit;
111 Widget<Gtk::MenuItem> _menu_help_about;
112 Widget<Gtk::MenuItem> _menu_jack_start;
113 Widget<Gtk::MenuItem> _menu_jack_stop;
114 Widget<Gtk::MenuItem> _menu_a2j_start;
115 Widget<Gtk::MenuItem> _menu_a2j_stop;
116 Widget<Gtk::MenuItem> _menu_load_project;
117 Widget<Gtk::MenuItem> _menu_save_all_projects;
118 Widget<Gtk::MenuItem> _menu_close_all_projects;
119 Widget<Gtk::MenuItem> _menu_store_positions;
120 Widget<Gtk::MenuItem> _menu_view_arrange;
121 Widget<Gtk::CheckMenuItem> _menu_view_projects;
122 Widget<Gtk::MenuItem> _menu_view_refresh;
123 Widget<Gtk::CheckMenuItem> _menu_view_toolbar;
124 Widget<Gtk::Viewport> _project_list_viewport;
125 Widget<Gtk::Label> _sample_rate_label;
126 Widget<Gtk::Toolbar> _toolbar;
127 Widget<Gtk::ToolButton> _zoom_full_but;
128 Widget<Gtk::ToolButton> _zoom_normal_but;
131 #include "globals.hpp"
133 #include "common.h"
134 #include "Widget.hpp"
135 #include <gtkmm.h>
137 #include "common.h"
139 #include <string.h>
140 #include <cmath>
141 #include <libgnomecanvasmm.h>
142 #include <libglademm/xml.h>
143 #include <gtk/gtkwindow.h>
144 #include <boost/format.hpp>
146 #include "project_list.hpp"
147 #include "session.hpp"
148 #include "globals.hpp"
149 //#include "load_projects_dialog.hpp"
150 #include "graph_canvas.h"
151 #include "../jack_proxy.h"
153 Patchage * g_app;
155 #define LOG_TO_STD
156 //#define LOG_TO_STATUS
158 /* Gtk helpers (resize combo boxes) */
160 static void
161 gtkmm_get_ink_pixel_size (Glib::RefPtr<Pango::Layout> layout,
162 int& width,
163 int& height)
165 Pango::Rectangle ink_rect = layout->get_ink_extents ();
167 width = (ink_rect.get_width() + PANGO_SCALE / 2) / PANGO_SCALE;
168 height = (ink_rect.get_height() + PANGO_SCALE / 2) / PANGO_SCALE;
171 static void
172 gtkmm_set_width_for_given_text (Gtk::Widget &w, const gchar *text,
173 gint hpadding/*, gint vpadding*/)
176 int old_width, old_height;
177 w.get_size_request(old_width, old_height);
179 int width, height;
180 w.ensure_style ();
182 gtkmm_get_ink_pixel_size (w.create_pango_layout (text), width, height);
183 w.set_size_request(width + hpadding, old_height);//height + vpadding);
186 /* end Gtk helpers */
189 #define INIT_WIDGET(x) x(g_xml, ((const char*)#x) + 1)
191 Patchage::Patchage()
192 : _max_dsp_load(0.0)
193 #if 0
194 , INIT_WIDGET(_about_win)
195 , INIT_WIDGET(_buffer_size_combo)
196 , INIT_WIDGET(_clear_load_but)
197 , INIT_WIDGET(_main_scrolledwin)
198 , INIT_WIDGET(_main_win)
199 , INIT_WIDGET(_main_xrun_progress)
200 , INIT_WIDGET(_main_a2j_status_label)
201 , INIT_WIDGET(_menu_file_quit)
202 , INIT_WIDGET(_menu_help_about)
203 , INIT_WIDGET(_menu_jack_start)
204 , INIT_WIDGET(_menu_jack_stop)
205 , INIT_WIDGET(_menu_a2j_start)
206 , INIT_WIDGET(_menu_a2j_stop)
207 , INIT_WIDGET(_menu_load_project)
208 , INIT_WIDGET(_menu_save_all_projects)
209 , INIT_WIDGET(_menu_close_all_projects)
210 , INIT_WIDGET(_menu_store_positions)
211 , INIT_WIDGET(_menu_view_arrange)
212 , INIT_WIDGET(_menu_view_projects)
213 , INIT_WIDGET(_menu_view_refresh)
214 , INIT_WIDGET(_menu_view_toolbar)
215 , INIT_WIDGET(_project_list_viewport)
216 , INIT_WIDGET(_sample_rate_label)
217 , INIT_WIDGET(_toolbar)
218 , INIT_WIDGET(_zoom_full_but)
219 , INIT_WIDGET(_zoom_normal_but)
220 #endif
222 g_app = this;
224 patchage_dbus_init();
226 graph_create(JACKDBUS_SERVICE, JACKDBUS_OBJECT, &g_jack_graph);
227 graph_canvas_create(1600 * 2, 1200 * 2, &g_jack_graph_canvas);
228 graph_canvas_attach(g_jack_graph_canvas, g_jack_graph);
229 graph_activate(g_jack_graph);
231 Glib::set_application_name("Patchage");
232 _about_win->property_program_name() = "Patchage";
233 _about_win->property_logo_icon_name() = "gladish";
234 gtk_window_set_default_icon_name("gladish");
236 gtkmm_set_width_for_given_text(*_buffer_size_combo, "4096 frames", 40);
238 _main_scrolledwin->add(*Glib::wrap(canvas_get_widget(graph_canvas_get_canvas(g_jack_graph_canvas))));
240 // _canvas->scroll_to(static_cast<int>(_canvas->width()/2 - 320),
241 // static_cast<int>(_canvas->height()/2 - 240)); // FIXME: hardcoded
243 _main_scrolledwin->property_hadjustment().get_value()->set_step_increment(10);
244 _main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10);
246 _main_scrolledwin->signal_scroll_event().connect(
247 sigc::mem_fun(this, &Patchage::on_scroll));
249 _buffer_size_combo->signal_changed().connect(
250 sigc::mem_fun(this, &Patchage::buffer_size_changed));
251 _clear_load_but->signal_clicked().connect(
252 sigc::mem_fun(this, &Patchage::clear_load));
253 _zoom_normal_but->signal_clicked().connect(sigc::bind(
254 sigc::mem_fun(this, &Patchage::zoom), 1.0));
255 // _zoom_full_but->signal_clicked().connect(sigc::mem_fun(_canvas.get(), &PatchageCanvas::zoom_full));
257 // _menu_load_project->signal_activate().connect(sigc::mem_fun(this, &Patchage::load_project_ask));
258 // _menu_save_all_projects->signal_activate().connect(sigc::mem_fun(this, &Patchage::save_all_projects));
259 // _menu_close_all_projects->signal_activate().connect(sigc::mem_fun(this, &Patchage::close_all_projects));
261 _menu_file_quit->signal_activate().connect(
262 sigc::mem_fun(this, &Patchage::on_quit));
263 _menu_view_refresh->signal_activate().connect(
264 sigc::mem_fun(this, &Patchage::refresh));
265 _menu_view_arrange->signal_activate().connect(
266 sigc::mem_fun(this, &Patchage::on_arrange));
267 _menu_view_toolbar->signal_activate().connect(
268 sigc::mem_fun(this, &Patchage::on_view_toolbar));
269 _menu_view_projects->signal_toggled().connect(
270 sigc::mem_fun(this, &Patchage::on_show_projects));
271 _menu_help_about->signal_activate().connect(
272 sigc::mem_fun(this, &Patchage::on_help_about));
274 Glib::wrap(canvas_get_widget(graph_canvas_get_canvas(g_jack_graph_canvas)))->show();
275 _main_win->present();
277 _about_win->set_transient_for(*_main_win);
279 // _a2j = new a2j_proxy;
281 //info_msg(str(boost::format("a2j jack client name is '%s'") % _a2j->get_jack_client_name()));
283 // _session = new session();
285 // _project_list = new project_list(this, _session);
286 // _project_list_viewport->hide();
288 // _lash = new lash_proxy(_session);
290 //_menu_jack_start->signal_activate().connect(sigc::mem_fun(_jack, &jack_proxy::start_server));
291 //_menu_jack_stop->signal_activate().connect(sigc::mem_fun(_jack, &jack_proxy::stop_server));
293 // _menu_a2j_start->signal_activate().connect(sigc::mem_fun(_a2j, &a2j_proxy::start_bridge));
294 // _menu_a2j_stop->signal_activate().connect(sigc::mem_fun(_a2j, &a2j_proxy::stop_bridge));
296 //jack_status_changed(_jack->is_started());
298 connect_widgets();
299 update_state();
301 // _canvas->grab_focus();
303 // Idle callback, check if we need to refresh
304 Glib::signal_timeout().connect(
305 sigc::mem_fun(this, &Patchage::idle_callback), 100);
308 Patchage::~Patchage()
310 //delete _lash;
311 //delete _project_list;
312 //delete _session;
313 //delete _a2j;
315 _about_win.destroy();
316 //_main_win.destroy();
318 patchage_dbus_uninit();
321 bool
322 Patchage::idle_callback()
324 update_load();
326 return true;
329 void
330 Patchage::update_toolbar()
332 #if 0
333 bool started;
335 started = _jack->is_started();
337 _buffer_size_combo->set_sensitive(started);
339 if (started)
341 _buffer_size_combo->set_active((int)log2f(_jack->buffer_size()) - 5);
343 #endif
346 void
347 Patchage::update_load()
349 #if 0
350 if (!_jack->is_started())
352 _main_xrun_progress->set_text("JACK stopped");
353 return;
356 char tmp_buf[8];
357 snprintf(tmp_buf, 8, "%zd", _jack->xruns());
359 _main_xrun_progress->set_text(std::string(tmp_buf) + " Dropouts");
361 float load = _jack->get_dsp_load();
363 load /= 100.0; // dbus returns it in percents, we use 0..1
365 if (load > _max_dsp_load)
367 _max_dsp_load = load;
368 _main_xrun_progress->set_fraction(load);
370 #endif
374 void
375 Patchage::zoom(double z)
377 // _canvas->set_zoom(z);
381 void
382 Patchage::refresh()
384 // assert(_canvas);
386 // _canvas->destroy();
388 // if (_jack)
389 // _jack->refresh();
391 // for (ItemList::iterator i = _canvas->items().begin(); i != _canvas->items().end(); ++i) {
392 // (*i)->resize();
393 // }
396 void
397 Patchage::clear_load()
399 #if 0
400 _main_xrun_progress->set_fraction(0.0);
401 _jack->reset_xruns();
402 _max_dsp_load = 0.0;
403 #endif
406 void
407 Patchage::update_state()
409 // for (ItemList::iterator i = _canvas->items().begin(); i != _canvas->items().end(); ++i) {
410 // shared_ptr<Module> module = dynamic_pointer_cast<Module>(*i);
411 // if (module)
412 // module->load_location();
413 // }
417 /** Update the sensitivity status of menus to reflect the present.
419 * (eg. disable "Connect to Jack" when Patchage is already connected to Jack)
421 void
422 Patchage::connect_widgets()
424 //_jack->signal_started.connect(sigc::bind(sigc::mem_fun(this, &Patchage::jack_status_changed), true));
425 //_jack->signal_stopped.connect(sigc::bind(sigc::mem_fun(this, &Patchage::jack_status_changed), false));
428 void
429 Patchage::jack_status_changed(
430 bool started)
432 update_toolbar();
434 _menu_jack_start->set_sensitive(!started);
435 _menu_jack_stop->set_sensitive(started);
436 _clear_load_but->set_sensitive(started);
437 if (!started)
439 _main_xrun_progress->set_fraction(0.0);
443 void
444 Patchage::on_arrange()
446 // assert(_canvas);
448 // _canvas->arrange();
452 void
453 Patchage::on_help_about()
455 _about_win->run();
456 _about_win->hide();
460 void
461 Patchage::on_quit()
463 _main_win->hide();
466 void
467 Patchage::on_show_projects()
469 if (_menu_view_projects->get_active())
470 _project_list_viewport->show();
471 else
472 _project_list_viewport->hide();
475 void
476 Patchage::on_view_toolbar()
478 if (_menu_view_toolbar->get_active())
479 _toolbar->show();
480 else
481 _toolbar->hide();
485 bool
486 Patchage::on_scroll(GdkEventScroll* ev)
488 lash_debug("ON SCROLL");
489 return false;
493 void
494 Patchage::buffer_size_changed()
496 #if 0
497 const int selected = _buffer_size_combo->get_active_row_number();
499 if (selected == -1)
501 update_toolbar();
503 else
505 uint32_t buffer_size = 1 << (selected+5);
507 // this check is temporal workaround for jack bug
508 // we skip setting buffer size if it same as acutal one
509 // proper place for such check is in jack
510 if (_jack->buffer_size() != buffer_size)
512 if (!_jack->set_buffer_size(buffer_size))
514 update_toolbar(); // reset combo box to actual value
518 #endif
521 void
522 Patchage::set_studio_availability(
523 bool available)
525 if (available)
527 _main_win->set_title("Active Studio - LADI Session Handler");
529 else
531 _main_win->set_title("LADI Session Handler");
533 //_project_list->set_lash_availability(available);
534 _menu_view_projects->set_active(available);
537 #if 0
538 void
539 Patchage::set_a2j_status(
540 unsigned int status)
542 const char * status_text;
544 switch (status)
546 case A2J_STATUS_NO_RESPONSE:
547 status_text = "A2J N/A";
548 _menu_a2j_start->set_sensitive(false);
549 _menu_a2j_stop->set_sensitive(false);
550 break;
551 case A2J_STATUS_BRIDGE_STOPPED:
552 status_text = "A2J bridge stopped";
553 _menu_a2j_start->set_sensitive(true);
554 _menu_a2j_stop->set_sensitive(false);
555 break;
556 case A2J_STATUS_BRIDGE_STARTED:
557 status_text = "A2J bridge started";
558 _menu_a2j_start->set_sensitive(false);
559 _menu_a2j_stop->set_sensitive(true);
560 break;
561 default:
562 error_msg(str(boost::format("Unknown A2J status %u") % status));
563 status_text = "Unknown A2J status";
564 _menu_a2j_start->set_sensitive(true);
565 _menu_a2j_stop->set_sensitive(true);
566 break;
569 _main_a2j_status_label->set_text(status_text);
572 void
573 Patchage::load_project_ask()
575 std::list<lash_project_info> projects;
577 _lash->get_available_projects(projects);
578 run_load_project_dialog(projects);
581 void
582 Patchage::load_project(
583 const std::string& project_name)
585 _lash->load_project(project_name);
588 void
589 Patchage::save_all_projects()
591 _lash->save_all_projects();
594 void
595 Patchage::save_project(
596 const std::string& project_name)
598 _lash->save_project(project_name);
601 void
602 Patchage::close_project(
603 const std::string& project_name)
605 _lash->close_project(project_name);
608 void
609 Patchage::close_all_projects()
611 _lash->close_all_projects();
614 void
615 Patchage::on_port_added(
616 const char * jack_client_name,
617 const char * jack_port_name,
618 PortType port_type,
619 bool is_input,
620 bool is_terminal)
622 bool is_a2j_mapped;
623 std::string canvas_client_name;
624 std::string canvas_port_name;
625 uint32_t alsa_client_id;
626 boost::shared_ptr<PatchageModule> module;
628 is_a2j_mapped = strcmp(_a2j->get_jack_client_name(), jack_client_name) == 0;
629 if (is_a2j_mapped)
631 if (!_a2j->map_jack_port(jack_port_name, canvas_client_name, canvas_port_name, alsa_client_id))
633 return;
636 canvas_port_name = str(boost::format(canvas_port_name + " [a2j:%u]") % alsa_client_id);
638 else
640 canvas_client_name = jack_client_name;
641 canvas_port_name = jack_port_name;
644 ModuleType module_type = InputOutput;
645 if (_state_manager->get_module_split(canvas_client_name, is_terminal && !is_a2j_mapped)) {
646 if (is_input) {
647 module_type = Input;
648 } else {
649 module_type = Output;
653 module = _canvas->find_module(canvas_client_name, module_type);
654 if (!module) {
655 module = boost::shared_ptr<PatchageModule>(new PatchageModule(this, canvas_client_name, module_type));
656 module->load_location();
657 _canvas->add_item(module);
660 if (module->get_port(canvas_port_name)) {
661 return;
664 boost::shared_ptr<PatchagePort> port = boost::shared_ptr<PatchagePort>(
665 new PatchagePort(
666 module,
667 canvas_port_name,
668 is_input,
669 _state_manager->get_port_color(port_type)));
671 port->type = port_type;
672 port->is_a2j_mapped = is_a2j_mapped;
673 if (is_a2j_mapped)
675 port->a2j_jack_port_name = jack_port_name;
678 module->add_port(port);
680 module->resize();
683 boost::shared_ptr<PatchagePort>
684 Patchage::lookup_port(
685 const char * jack_client_name,
686 const char * jack_port_name)
688 if (strcmp(_a2j->get_jack_client_name(), jack_client_name) == 0)
690 return _canvas->lookup_port_by_a2j_jack_port_name(jack_port_name);
693 return _canvas->get_port(jack_client_name, jack_port_name);
696 void
697 Patchage::on_port_removed(
698 const char * jack_client_name,
699 const char * jack_port_name)
701 boost::shared_ptr<PatchagePort> port = lookup_port(jack_client_name, jack_port_name);
702 if (!port) {
703 error_msg(str(boost::format("Unable to remove unknown port '%s':'%s'") % jack_client_name % jack_port_name));
704 return;
707 boost::shared_ptr<PatchageModule> module = dynamic_pointer_cast<PatchageModule>(port->module().lock());
709 module->remove_port(port);
710 port.reset();
712 // No empty modules (for now)
713 if (module->num_ports() == 0) {
714 _canvas->remove_item(module);
715 module.reset();
716 } else {
717 module->resize();
721 void
722 Patchage::on_ports_connected(
723 const char * jack_client1_name,
724 const char * jack_port1_name,
725 const char * jack_client2_name,
726 const char * jack_port2_name)
728 boost::shared_ptr<PatchagePort> port1 = lookup_port(jack_client1_name, jack_port1_name);
729 if (!port1) {
730 error_msg((std::string)"Unable to connect unknown port '" + jack_port1_name + "' of client '" + jack_client1_name + "'");
731 return;
734 boost::shared_ptr<PatchagePort> port2 = lookup_port(jack_client2_name, jack_port2_name);
735 if (!port2) {
736 error_msg((std::string)"Unable to connect unknown port '" + jack_port2_name + "' of client '" + jack_client2_name + "'");
737 return;
740 _canvas->add_connection(port1, port2, port1->color() + 0x22222200);
743 void
744 Patchage::on_ports_disconnected(
745 const char * jack_client1_name,
746 const char * jack_port1_name,
747 const char * jack_client2_name,
748 const char * jack_port2_name)
750 boost::shared_ptr<PatchagePort> port1 = lookup_port(jack_client1_name, jack_port1_name);
751 if (!port1) {
752 error_msg((std::string)"Unable to disconnect unknown port '" + jack_port1_name + "' of client '" + jack_client1_name + "'");
753 return;
756 boost::shared_ptr<PatchagePort> port2 = lookup_port(jack_client2_name, jack_port2_name);
757 if (!port2) {
758 error_msg((std::string)"Unable to disconnect unknown port '" + jack_port2_name + "' of client '" + jack_client2_name + "'");
759 return;
762 _canvas->remove_connection(port1, port2);
765 static
766 bool
767 port_type_match(
768 boost::shared_ptr<PatchagePort> port1,
769 boost::shared_ptr<PatchagePort> port2)
771 return port1->type == port2->type;
774 void
775 Patchage::get_port_jack_names(
776 boost::shared_ptr<PatchagePort> port,
777 std::string& jack_client_name,
778 std::string& jack_port_name)
780 if (port->is_a2j_mapped)
782 jack_client_name = _a2j->get_jack_client_name();
783 jack_port_name = port->a2j_jack_port_name;
785 else
787 jack_client_name = port->module().lock()->name();
788 jack_port_name = port->name();
792 void
793 Patchage::connect(
794 boost::shared_ptr<PatchagePort> port1,
795 boost::shared_ptr<PatchagePort> port2)
797 std::string jack_client1_name;
798 std::string jack_port1_name;
799 std::string jack_client2_name;
800 std::string jack_port2_name;
802 if (port_type_match(port1, port2))
804 get_port_jack_names(port1, jack_client1_name, jack_port1_name);
805 get_port_jack_names(port2, jack_client2_name, jack_port2_name);
807 _jack->connect(
808 jack_client1_name.c_str(),
809 jack_port1_name.c_str(),
810 jack_client2_name.c_str(),
811 jack_port2_name.c_str());
813 else
815 status_msg("ERROR: Attempt to connect ports with mismatched types");
819 void
820 Patchage::disconnect(
821 boost::shared_ptr<PatchagePort> port1,
822 boost::shared_ptr<PatchagePort> port2)
824 std::string jack_client1_name;
825 std::string jack_port1_name;
826 std::string jack_client2_name;
827 std::string jack_port2_name;
829 if (port_type_match(port1, port2))
831 get_port_jack_names(port1, jack_client1_name, jack_port1_name);
832 get_port_jack_names(port2, jack_client2_name, jack_port2_name);
834 _jack->disconnect(
835 jack_client1_name.c_str(),
836 jack_port1_name.c_str(),
837 jack_client2_name.c_str(),
838 jack_port2_name.c_str());
840 else
842 status_msg("ERROR: Attempt to disconnect ports with mismatched types");
846 bool
847 Patchage::is_canvas_empty()
849 return _canvas->items().empty();
851 #endif
852 #endif
854 graph_canvas_handle g_jack_graph_canvas;
855 graph_handle g_jack_graph;
857 int main(int argc, char** argv)
859 GtkWidget * main_win;
860 GtkScrolledWindow * main_scrolledwin;
861 GtkWidget * canvas_widget;
863 gtk_init(&argc, &argv);
865 if (!canvas_init())
867 lash_error("Canvas initialization failed.");
868 return 1;
871 if (!init_glade())
873 return 1;
876 /* Obtain widgets that we need */
877 main_win = get_glade_widget("main_win");
878 main_scrolledwin = GTK_SCROLLED_WINDOW(get_glade_widget("main_scrolledwin"));
880 patchage_dbus_init();
882 graph_create(JACKDBUS_SERVICE, JACKDBUS_OBJECT, &g_jack_graph);
883 graph_canvas_create(1600 * 2, 1200 * 2, &g_jack_graph_canvas);
884 graph_canvas_attach(g_jack_graph_canvas, g_jack_graph);
885 graph_activate(g_jack_graph);
887 canvas_widget = canvas_get_widget(graph_canvas_get_canvas(g_jack_graph_canvas));
889 gtk_widget_show(canvas_widget);
891 //gtkmm_set_width_for_given_text(*_buffer_size_combo, "4096 frames", 40);
893 gtk_container_add(GTK_CONTAINER(main_scrolledwin), canvas_widget);
895 // _canvas->scroll_to(static_cast<int>(_canvas->width()/2 - 320), static_cast<int>(_canvas->height()/2 - 240)); // FIXME: hardcoded
897 //_main_scrolledwin->property_hadjustment().get_value()->set_step_increment(10);
898 //_main_scrolledwin->property_vadjustment().get_value()->set_step_increment(10);
900 g_signal_connect(G_OBJECT(main_win), "destroy", G_CALLBACK(gtk_main_quit), NULL);
901 g_signal_connect(G_OBJECT(get_glade_widget("menu_file_quit")), "activate", G_CALLBACK(gtk_main_quit), NULL);
903 gtk_widget_show(main_win);
905 //_about_win->set_transient_for(*_main_win);
907 gtk_main();
909 uninit_glade();
911 return 0;