Basic region naming test.
[ardour.git] / gtk2_ardour / playlist_selector.cc
1 /*
2     Copyright (C) 2004 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
21 #include <gtkmm/button.h>
22
23 #include "ardour/audio_track.h"
24 #include "ardour/audioplaylist.h"
25 #include "ardour/playlist.h"
26 #include "ardour/session_playlist.h"
27
28 #include <gtkmm2ext/gtk_ui.h>
29
30 #include "playlist_selector.h"
31 #include "route_ui.h"
32 #include "gui_thread.h"
33
34 #include "i18n.h"
35
36 using namespace std;
37 using namespace Gtk;
38 using namespace Gtkmm2ext;
39 using namespace ARDOUR;
40 using namespace PBD;
41
42 PlaylistSelector::PlaylistSelector ()
43         : ArdourDialog (_("Playlists"))
44 {
45         rui = 0;
46
47         set_position (WIN_POS_MOUSE);
48         set_name ("PlaylistSelectorWindow");
49         set_modal(true);
50         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
51         set_size_request (300, 200);
52
53         model = TreeStore::create (columns);
54         tree.set_model (model);
55         tree.append_column (_("Playlists grouped by track"), columns.text);
56
57         scroller.add (tree);
58         scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
59
60         get_vbox()->set_border_width (6);
61         get_vbox()->set_spacing (12);
62
63         get_vbox()->pack_start (scroller);
64
65         Button* b = add_button (_("Close"), RESPONSE_CANCEL);
66         b->signal_clicked().connect (sigc::mem_fun(*this, &PlaylistSelector::close_button_click));
67
68 }
69
70 PlaylistSelector::~PlaylistSelector ()
71 {
72         clear_map ();
73 }
74
75 void
76 PlaylistSelector::clear_map ()
77 {
78         for (TrackPlaylistMap::iterator x = trpl_map.begin(); x != trpl_map.end(); ++x) {
79                 delete x->second;
80         }
81         trpl_map.clear ();
82 }
83
84 bool
85 PlaylistSelector::on_unmap_event (GdkEventAny* ev)
86 {
87         clear_map ();
88         if (model) {
89                 model->clear ();
90         }
91         return Dialog::on_unmap_event (ev);
92 }
93
94 void
95 PlaylistSelector::show_for (RouteUI* ruix)
96 {
97         vector<const char*> item;
98         string str;
99
100         rui = ruix;
101
102         set_title (string_compose (_("Playlist for %1"), rui->route()->name()));
103
104         clear_map ();
105         select_connection.disconnect ();
106
107         model->clear ();
108
109         _session->playlists->foreach (this, &PlaylistSelector::add_playlist_to_map);
110
111         boost::shared_ptr<Track> this_track = rui->track();
112
113         TreeModel::Row others = *(model->append ());
114
115         others[columns.text] = _("Other tracks");
116         boost::shared_ptr<Playlist> proxy = others[columns.playlist];
117         proxy.reset ();
118
119         for (TrackPlaylistMap::iterator x = trpl_map.begin(); x != trpl_map.end(); ++x) {
120
121                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (_session->route_by_id (x->first));
122                 
123                 /* legacy sessions stored the diskstream ID as the original
124                  * playlist owner. so try there instead.
125                  */
126
127                 if (tr == 0) {
128                         tr = _session->track_by_diskstream_id (x->first);
129                 }
130
131                 if (tr == 0) {
132                         continue;
133                 }
134
135                 /* add a node for the track */
136
137                 string nodename;
138
139                 if (tr->name().empty()) {
140                         nodename = _("unassigned");
141                 } else {
142                         nodename = tr->name().c_str();
143                 }
144
145                 TreeModel::Row row;
146                 TreeModel::Row selected_row;
147                 bool have_selected = false;
148                 TreePath this_path;
149
150                 if (tr == this_track) {
151                         row = *(model->prepend());
152                         row[columns.text] = nodename;
153                         boost::shared_ptr<Playlist> proxy = row[columns.playlist];
154                         proxy.reset ();
155                 } else {
156                         row = *(model->append (others.children()));
157                         row[columns.text] = nodename;
158                         boost::shared_ptr<Playlist> proxy = row[columns.playlist];
159                         proxy.reset ();
160                 }
161
162                 /* Now insert all the playlists for this diskstream/track in a subtree */
163
164                 list<boost::shared_ptr<Playlist> >* pls = x->second;
165
166                 for (list<boost::shared_ptr<Playlist> >::iterator p = pls->begin(); p != pls->end(); ++p) {
167
168                         TreeModel::Row child_row;
169
170                         child_row = *(model->append (row.children()));
171                         child_row[columns.text] = (*p)->name();
172                         child_row[columns.playlist] = *p;
173
174                         if (*p == this_track->playlist()) {
175                                 selected_row = child_row;
176                                 have_selected = true;
177                         }
178                 }
179
180                 if (have_selected) {
181                         tree.get_selection()->select (selected_row);
182                 }
183         }
184
185         // Add unassigned (imported) playlists to the list
186         list<boost::shared_ptr<Playlist> > unassigned;
187         _session->playlists->unassigned (unassigned);
188
189         TreeModel::Row row;
190         TreeModel::Row selected_row;
191         bool have_selected = false;
192         TreePath this_path;
193
194         row = *(model->append (others.children()));
195         row[columns.text] = _("Imported");
196         proxy = row[columns.playlist];
197         proxy.reset ();
198
199         for (list<boost::shared_ptr<Playlist> >::iterator p = unassigned.begin(); p != unassigned.end(); ++p) {
200                 TreeModel::Row child_row;
201
202                 child_row = *(model->append (row.children()));
203                 child_row[columns.text] = (*p)->name();
204                 child_row[columns.playlist] = *p;
205
206                 if (*p == this_track->playlist()) {
207                         selected_row = child_row;
208                         have_selected = true;
209                 }
210
211                 if (have_selected) {
212                         tree.get_selection()->select (selected_row);
213                 }
214         }
215
216         show_all ();
217         select_connection = tree.get_selection()->signal_changed().connect (sigc::mem_fun(*this, &PlaylistSelector::selection_changed));
218 }
219
220 void
221 PlaylistSelector::add_playlist_to_map (boost::shared_ptr<Playlist> pl)
222 {
223         boost::shared_ptr<AudioPlaylist> apl;
224
225         if (pl->frozen()) {
226                 return;
227         }
228
229         if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) == 0) {
230                 return;
231         }
232
233         TrackPlaylistMap::iterator x;
234
235         if ((x = trpl_map.find (apl->get_orig_track_id())) == trpl_map.end()) {
236                 x = trpl_map.insert (trpl_map.end(), make_pair (apl->get_orig_track_id(), new list<boost::shared_ptr<Playlist> >));
237         }
238
239         x->second->push_back (pl);
240 }
241
242 void
243 PlaylistSelector::close_button_click ()
244 {
245         rui = 0;
246         hide ();
247 }
248
249 void
250 PlaylistSelector::selection_changed ()
251 {
252         boost::shared_ptr<Playlist> playlist;
253
254         TreeModel::iterator iter = tree.get_selection()->get_selected();
255
256         if (!iter || rui == 0) {
257                 /* nothing selected */
258                 return;
259         }
260
261         if ((playlist = ((*iter)[columns.playlist])) != 0) {
262
263                 boost::shared_ptr<AudioTrack> at;
264                 boost::shared_ptr<AudioPlaylist> apl;
265
266                 if ((at = rui->audio_track()) == 0) {
267                         /* eh? */
268                         return;
269                 }
270
271                 if ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (playlist)) == 0) {
272                         /* eh? */
273                         return;
274                 }
275
276                 at->use_playlist (apl);
277
278                 hide ();
279         }
280
281 }
282