6 #include <gtkmm/main.h>
7 #include <gtkmm/window.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>
21 using namespace Gtkmm2ext;
24 struct ModelColumns : public TreeModel::ColumnRecord {
30 TreeModelColumn<bool> used;
31 TreeModelColumn<ustring> text;
32 TreeModelColumn<jack_port_t*> port;
38 fill_it (RefPtr<TreeStore> model, TreeView* display, ModelColumns* columns)
40 RefPtr<TreeModel> old = display->get_model();
41 display->set_model (RefPtr<TreeStore>(0));
46 typedef map<string,vector<pair<string,string> > > PortMap;
50 ports = jack_get_ports (jack, "", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput);
56 /* find all the client names and group their ports into a list-by-client */
58 for (int n = 0; ports[n]; ++n) {
60 pair<string,vector<pair<string,string> > > newpair;
61 pair<string,string> strpair;
62 std::pair<PortMap::iterator,bool> result;
64 string str = ports[n];
65 string::size_type pos;
70 newpair.first = str.substr (0, pos);
71 portname = str.substr (pos+1);
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.
79 result = portmap.insert (newpair);
81 strpair.first = portname;
84 result.first->second.push_back (strpair);
88 for (i = portmap.begin(); i != portmap.end(); ++i) {
90 /* i->first is a client name, i->second is a PortMap of all of its ports */
92 TreeModel::Row parent = *(model->append());
94 parent[columns->used] = false;
95 parent[columns->text] = i->first;
96 parent[columns->port] = 0;
98 for (vector<pair<string,string> >::iterator s = i->second.begin(); s != i->second.end(); ++s) {
100 /* s->first is a port name */
102 TreeModel::Row row = *(model->append (parent.children()));
104 row[columns->used] = ((random()%2) == 1);
105 row[columns->text] = s->first;
106 row[columns->port] = (jack_port_t*) random();
111 display->set_model (old);
115 selection_changed (RefPtr<TreeModel> model, TreeView* display, ModelColumns* columns)
117 // TreeSelection::ListHandle_Path selection = display->get_selection()->get_selected_rows ();
119 // for (TreeSelection::ListHandle_Path::iterator x = selection.begin(); x != selection.end(); ++x) {
120 // cerr << "selected: " << (*(model->get_iter (*x)))[columns->text] << endl;
125 selection_filter (const RefPtr<TreeModel>& model, const TreeModel::Path& path, bool yn, ModelColumns* columns)
127 return (*(model->get_iter (path)))[columns->port] != 0;
131 object_drop (string type, uint32_t cnt, void** ptr)
133 cerr << "Got an object drop of " << cnt << " pointer(s) of type " << type << endl;
137 main (int argc, char* argv[])
139 Main app (&argc, &argv);
143 Button rescan ("rescan");
144 ScrolledWindow scrollerA;
145 ScrolledWindow scrollerB;
146 DnDTreeView displayA;
147 DnDTreeView displayB;
148 ModelColumns columns;
150 if ((jack = jack_client_new ("itest")) == NULL) {
154 RefPtr<TreeStore> modelA = TreeStore::create (columns);
155 RefPtr<TreeStore> modelB = TreeStore::create (columns);
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));
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));
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));
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));
179 scrollerA.add (displayA);
180 scrollerB.add (displayB);
182 hpacker.pack_start (scrollerA);
183 hpacker.pack_start (scrollerB);
185 vpacker.pack_start (hpacker);
186 vpacker.pack_start (rescan, false, false);
189 win.set_size_request (500, 400);
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));
195 fill_it (modelA, &displayA, &columns);
196 fill_it (modelB, &displayB, &columns);
198 displayA.expand_all();
199 displayB.expand_all();
203 jack_client_close (jack);