Send MMC/MTC options will stick now, and prevent the engine from messing
[ardour.git] / gtk2_ardour / itest.cc
1 #include <map>
2 #include <vector>
3 #include <string>
4 #include <iostream>
5
6 #include <gtkmm/main.h>
7 #include <gtkmm/window.h>
8 #include <gtkmm/box.h>
9 #include <gtkmm/scrolledwindow.h>
10 #include <gtkmm2ext/dndtreeview.h>
11 #include <gtkmm/treemodel.h>
12 #include <gtkmm/treestore.h>
13 #include <gtkmm/treepath.h>
14 #include <gtkmm/button.h>
15 #include <gtkmm/window.h>
16 #include <jack/jack.h>
17
18 using namespace std;
19 using namespace sigc;
20 using namespace Gtk;
21 using namespace Gtkmm2ext;
22 using namespace Glib;
23
24 struct ModelColumns : public TreeModel::ColumnRecord {
25     ModelColumns() { 
26             add (used);
27             add (text);
28             add (port);
29     }
30     TreeModelColumn<bool>         used;
31     TreeModelColumn<ustring>      text;
32     TreeModelColumn<jack_port_t*> port;
33 };
34
35 jack_client_t* jack;
36
37 void
38 fill_it (RefPtr<TreeStore> model, TreeView* display, ModelColumns* columns)
39 {
40         RefPtr<TreeModel> old = display->get_model();
41         display->set_model (RefPtr<TreeStore>(0));
42
43         model->clear ();
44         
45         const char ** ports;
46         typedef map<string,vector<pair<string,string> > > PortMap;
47         PortMap portmap;
48         PortMap::iterator i;
49         
50         ports = jack_get_ports (jack, "", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput);
51
52         if (ports == 0) {
53                 goto out;
54         }
55
56         /* find all the client names and group their ports into a list-by-client */
57         
58         for (int n = 0; ports[n]; ++n) {
59
60                 pair<string,vector<pair<string,string> > > newpair;
61                 pair<string,string> strpair;
62                 std::pair<PortMap::iterator,bool> result;
63
64                 string str = ports[n];
65                 string::size_type pos;
66                 string portname;
67
68                 pos = str.find (':');
69
70                 newpair.first = str.substr (0, pos); 
71                 portname = str.substr (pos+1);
72
73                 /* this may or may not succeed at actually inserting. 
74                    we don't care, however: we just want an iterator
75                    that gives us either the inserted element or
76                    the existing one with the same name.
77                 */
78
79                 result = portmap.insert (newpair);
80
81                 strpair.first = portname;
82                 strpair.second = str;
83
84                 result.first->second.push_back (strpair);
85         }
86
87
88         for (i = portmap.begin(); i != portmap.end(); ++i) {
89
90                 /* i->first is a client name, i->second is a PortMap of all of its ports */
91
92                 TreeModel::Row parent = *(model->append());
93
94                 parent[columns->used] = false;
95                 parent[columns->text] = i->first;
96                 parent[columns->port] = 0;
97
98                 for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) {
99
100                         /* s->first is a port name */
101                         
102                         TreeModel::Row row = *(model->append (parent.children()));
103
104                         row[columns->used] = ((random()%2) == 1);
105                         row[columns->text] = s->first;
106                         row[columns->port] = (jack_port_t*) random();
107                 }
108         }
109
110   out:
111         display->set_model (old);
112 }
113
114 void
115 selection_changed (RefPtr<TreeModel> model, TreeView* display, ModelColumns* columns)
116 {
117 //      TreeSelection::ListHandle_Path selection = display->get_selection()->get_selected_rows ();
118 //
119 //      for (TreeSelection::ListHandle_Path::iterator x = selection.begin(); x != selection.end(); ++x) {
120 //              cerr << "selected: " << (*(model->get_iter (*x)))[columns->text] << endl;
121 //      }
122 }
123
124 bool
125 selection_filter (const RefPtr<TreeModel>& model, const TreeModel::Path& path, bool yn, ModelColumns* columns)
126 {
127         return (*(model->get_iter (path)))[columns->port] != 0;
128 }
129
130 void
131 object_drop (string type, uint32_t cnt, void** ptr)
132 {
133         cerr << "Got an object drop of " << cnt << " pointer(s) of type " << type << endl;
134 }
135
136 int
137 main (int argc, char* argv[])
138 {
139         Main app (&argc, &argv);
140         Window win;
141         VBox   vpacker;
142         HBox   hpacker;
143         Button rescan ("rescan");
144         ScrolledWindow scrollerA;
145         ScrolledWindow scrollerB;
146         DnDTreeView displayA;
147         DnDTreeView displayB;
148         ModelColumns columns;
149
150         if ((jack = jack_client_new ("itest")) == NULL) {
151                 return -1;
152         }
153
154         RefPtr<TreeStore> modelA = TreeStore::create (columns);
155         RefPtr<TreeStore> modelB = TreeStore::create (columns);
156         
157         displayA.set_model (modelA);
158         displayA.append_column ("Use", columns.used);
159         displayA.append_column ("Source/Port", columns.text);
160         displayA.set_reorderable (true);
161         displayA.add_object_drag (columns.port.index(), "ports");
162         displayA.signal_object_drop.connect (ptr_fun (object_drop));
163         
164         displayA.get_selection()->set_mode (SELECTION_MULTIPLE);
165         displayA.get_selection()->set_select_function (bind (ptr_fun (selection_filter), &columns));
166         displayA.get_selection()->signal_changed().connect (bind (ptr_fun (selection_changed), modelA, &displayA, &columns));
167
168         displayB.set_model (modelB);
169         displayB.append_column ("Use", columns.used);
170         displayB.append_column ("Source/Port", columns.text);
171         displayB.set_reorderable (true);
172         displayB.add_object_drag (columns.port.index(), "ports");
173         displayB.signal_object_drop.connect (ptr_fun (object_drop));
174
175         displayB.get_selection()->set_mode (SELECTION_MULTIPLE);
176         displayB.get_selection()->set_select_function (bind (ptr_fun (selection_filter), &columns));
177         displayB.get_selection()->signal_changed().connect (bind (ptr_fun (selection_changed), modelB, &displayB, &columns));
178
179         scrollerA.add (displayA);
180         scrollerB.add (displayB);
181
182         hpacker.pack_start (scrollerA);
183         hpacker.pack_start (scrollerB);
184
185         vpacker.pack_start (hpacker);
186         vpacker.pack_start (rescan, false, false);
187         
188         win.add (vpacker);
189         win.set_size_request (500, 400);
190         win.show_all ();
191         
192         rescan.signal_clicked().connect (bind (ptr_fun (fill_it), modelA, &displayA, &columns));
193         rescan.signal_clicked().connect (bind (ptr_fun (fill_it), modelB, &displayB, &columns));
194         
195         fill_it (modelA, &displayA, &columns);
196         fill_it (modelB, &displayB, &columns);
197
198         displayA.expand_all();
199         displayB.expand_all();
200
201         app.run ();
202
203         jack_client_close (jack);
204 }