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