2 Copyright (C) 2000 Paul Davis
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.
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.
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.
26 #include <pbd/basename.h>
28 #include <ardour/audioregion.h>
29 #include <ardour/session_region.h>
31 #include <gtkmm2ext/stop_signal.h>
35 #include "ardour_ui.h"
36 #include "gui_thread.h"
41 using namespace ARDOUR;
43 using namespace Editing;
45 #define wave_cursor_width 43
46 #define wave_cursor_height 61
47 #define wave_cursor_x_hot 0
48 #define wave_cursor_y_hot 25
49 static const gchar wave_cursor_bits[] = {
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
54 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
56 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
58 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff,
60 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
62 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
64 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
66 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x00, 0x04, 0x00,
68 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x0c, 0x08, 0x0c, 0x00,
70 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04,
72 0x02, 0x3c, 0x18, 0x0c, 0x04, 0x02, 0x02, 0x7c, 0x18, 0x1c, 0x0c,
74 0x82, 0xfc, 0x38, 0x1c, 0x0c, 0x02, 0xc2, 0xfc, 0x78, 0x3c, 0x1c,
76 0xe2, 0xfd, 0xf9, 0x7d, 0x1c, 0x02, 0xf2, 0xff, 0xfb, 0xff, 0x1c,
78 0xfa, 0xff, 0xfb, 0xff, 0x3f, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff,
80 0xfe, 0xff, 0xff, 0xff, 0xff, 0x03, 0xfa, 0xff, 0xff, 0xff, 0x3f,
82 0xf2, 0xff, 0xfb, 0xfd, 0x3c, 0x02, 0xe2, 0xfd, 0x7b, 0x7c, 0x1c,
84 0xc2, 0xfc, 0x39, 0x3c, 0x1c, 0x02, 0x82, 0xfc, 0x18, 0x1c, 0x1c,
86 0x02, 0xfc, 0x18, 0x1c, 0x0c, 0x02, 0x02, 0x7c, 0x18, 0x0c, 0x0c,
88 0x02, 0x3c, 0x08, 0x0c, 0x04, 0x02, 0x02, 0x1c, 0x08, 0x0c, 0x04,
90 0x02, 0x1c, 0x08, 0x0c, 0x00, 0x02, 0x02, 0x0c, 0x00, 0x04, 0x00,
92 0x02, 0x04, 0x00, 0x04, 0x00, 0x02, 0x02, 0x04, 0x00, 0x00, 0x00,
94 0x02, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
96 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
98 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
100 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0xfe, 0xff, 0xff, 0xff, 0xff,
102 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
104 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00,
106 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
108 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
112 #define wave_cursor_mask_width 43
113 #define wave_cursor_mask_height 61
114 #define wave_cursor_mask_x_hot 0
115 #define wave_cursor_mask_y_hot 25
116 static const gchar wave_cursor_mask_bits[] = {
117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
135 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0c, 0x08, 0x0c, 0x00,
137 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04,
139 0x00, 0x3c, 0x18, 0x0c, 0x04, 0x00, 0x00, 0x7c, 0x18, 0x1c, 0x0c,
141 0x80, 0xfc, 0x38, 0x1c, 0x0c, 0x00, 0xc0, 0xfc, 0x78, 0x3c, 0x1c,
143 0xe0, 0xfd, 0xf9, 0x7d, 0x1c, 0x00, 0xf0, 0xff, 0xfb, 0xff, 0x1c,
145 0xf8, 0xff, 0xfb, 0xff, 0x3f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff,
147 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0xff, 0x3f,
149 0xf0, 0xff, 0xfb, 0xfd, 0x3c, 0x00, 0xe0, 0xfd, 0x7b, 0x7c, 0x1c,
151 0xc0, 0xfc, 0x39, 0x3c, 0x1c, 0x00, 0x80, 0xfc, 0x18, 0x1c, 0x1c,
153 0x00, 0xfc, 0x18, 0x1c, 0x0c, 0x00, 0x00, 0x7c, 0x18, 0x0c, 0x0c,
155 0x00, 0x3c, 0x08, 0x0c, 0x04, 0x00, 0x00, 0x1c, 0x08, 0x0c, 0x04,
157 0x00, 0x1c, 0x08, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x04, 0x00,
159 0x00, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
161 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
179 GdkCursor *wave_cursor = 0;
182 Editor::handle_audio_region_removed (AudioRegion* ignored)
184 redisplay_regions ();
188 Editor::handle_new_audio_region (AudioRegion *region)
190 /* don't copy region - the one we are being notified
191 about belongs to the session, and so it will
194 add_audio_region_to_region_display (region);
198 Editor::region_hidden (Region* r)
200 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::region_hidden), r));
202 redisplay_regions ();
206 Editor::add_audio_region_to_region_display (AudioRegion *region)
208 using namespace Gtk::CTree_Helpers;
210 vector<const char*> item;
212 RowList::iterator tmpi;
215 if (!show_automatic_regions_in_region_list && region->automatic()) {
219 if (region->hidden()) {
221 if (region_list_hidden_node == region_list_display.rows().end()) {
223 item.push_back (_("hidden"));
224 region_list_hidden_node = region_list_display.rows().insert (region_list_display.rows().end(),
226 (*region_list_hidden_node).set_data (0);
227 (*region_list_hidden_node).set_leaf (false);
231 if (region->n_channels() > 1) {
232 str = string_compose("%1 [%2]", region->name(), region->n_channels());
233 item.push_back (str.c_str());
235 item.push_back (region->name().c_str());
238 tmpi = region_list_hidden_node->subtree().insert (region_list_hidden_node->subtree().end(),
240 (*tmpi).set_data (region);
243 } else if (region->whole_file()) {
247 if (region->source().name()[0] == '/') { // external file
249 if (region->whole_file()) {
251 str += PBD::basename_nosuffix (region->source().name());
253 str = region->name();
258 str = region->name();
262 item.push_back (str.c_str());
264 tmpi = region_list_display.rows().insert (region_list_display.rows().end(),
267 (*tmpi).set_data (region);
268 (*tmpi).set_leaf (false);
274 /* find parent node, add as new child */
276 for (i = region_list_display.rows().begin(); i != region_list_display.rows().end(); ++i) {
278 AudioRegion* r = static_cast<AudioRegion*> ((*i).get_data());
280 if (r && r->whole_file()) {
282 if (region->source_equivalent (*r)) {
286 if (region->n_channels() > 1) {
287 str = string_compose("%1 [%2]", region->name(), region->n_channels());
288 item.push_back (str.c_str());
290 item.push_back (region->name().c_str());
294 tmpi = i->subtree().insert (i->subtree().end(), Element (item));
295 (*tmpi).set_data (region);
305 if (region->n_channels() > 1) {
306 str = string_compose("%1 [%2]", region->name(), region->n_channels());
307 item.push_back (str.c_str());
309 item.push_back (region->name().c_str());
312 tmpi = region_list_display.rows().insert (region_list_display.rows().end(), Element (item));
313 (*tmpi).set_data (region);
314 (*tmpi).set_leaf (true);
318 Editor::insert_into_tmp_audio_regionlist(AudioRegion* region)
320 /* keep all whole files at the beginning */
322 if (region->whole_file()) {
323 tmp_audio_region_list.push_front (region);
325 tmp_audio_region_list.push_back (region);
330 Editor::redisplay_regions ()
333 region_list_display.freeze ();
334 region_list_clear ();
335 region_list_hidden_node = region_list_display.rows().end();
337 /* now add everything we have, via a temporary list used to help with
341 tmp_audio_region_list.clear();
342 session->foreach_audio_region (this, &Editor::insert_into_tmp_audio_regionlist);
344 for (list<AudioRegion*>::iterator r = tmp_audio_region_list.begin(); r != tmp_audio_region_list.end(); ++r) {
345 add_audio_region_to_region_display (*r);
348 region_list_display.sort ();
349 region_list_display.thaw ();
354 Editor::region_list_clear ()
356 /* ---------------------------------------- */
357 /* XXX MAKE ME A FUNCTION (no CTree::clear() in gtkmm 1.2) */
359 gtk_ctree_remove_node (region_list_display.gobj(), NULL);
361 /* ---------------------------------------- */
365 Editor::region_list_column_click (gint col)
369 if (region_list_menu == 0) {
370 build_region_list_menu ();
373 if (region_list_display.selection().size() != 0) {
379 for (vector<MenuItem*>::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) {
380 (*i)->set_sensitive (sensitive);
383 region_list_menu->popup (0, 0);
387 Editor::build_region_list_menu ()
389 using namespace Gtk::Menu_Helpers;
391 region_list_menu = new Menu;
393 MenuList& items = region_list_menu->items();
394 region_list_menu->set_name ("ArdourContextMenu");
396 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_region_from_region_list)));
397 rl_context_menu_region_items.push_back (items.back());
398 items.push_back (MenuElem (_("Hide"), mem_fun(*this, &Editor::hide_region_from_region_list)));
399 rl_context_menu_region_items.push_back (items.back());
400 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_region_from_region_list)));
401 rl_context_menu_region_items.push_back (items.back());
404 items.push_back (SeparatorElem());
407 // items.push_back (MenuElem (_("Find")));
408 items.push_back (CheckMenuElem (_("Show all"), mem_fun(*this, &Editor::toggle_full_region_list)));
409 toggle_full_region_list_item = static_cast<CheckMenuItem*> (items.back());
411 Gtk::Menu *sort_menu = manage (new Menu);
412 MenuList& sort_items = sort_menu->items();
413 sort_menu->set_name ("ArdourContextMenu");
414 RadioMenuItem::Group sort_order_group;
415 RadioMenuItem::Group sort_type_group;
417 sort_items.push_back (RadioMenuElem (sort_order_group, _("Ascending"),
418 bind (mem_fun(*this, &Editor::reset_region_list_sort_direction), true)));
419 sort_items.push_back (RadioMenuElem (sort_order_group, _("Descending"),
420 bind (mem_fun(*this, &Editor::reset_region_list_sort_direction), false)));
421 sort_items.push_back (SeparatorElem());
423 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Name"),
424 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByName)));
425 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Length"),
426 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByLength)));
427 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Position"),
428 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByPosition)));
429 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Timestamp"),
430 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByTimestamp)));
431 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region Start in File"),
432 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByStartInFile)));
433 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Region End in File"),
434 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), ByEndInFile)));
435 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Name"),
436 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileName)));
437 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Length"),
438 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileLength)));
439 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source File Creation Date"),
440 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileCreationDate)));
441 sort_items.push_back (RadioMenuElem (sort_type_group, _("By Source Filesystem"),
442 bind (mem_fun(*this, &Editor::reset_region_list_sort_type), BySourceFileFS)));
444 items.push_back (MenuElem (_("Sorting"), *sort_menu));
445 items.push_back (SeparatorElem());
447 // items.push_back (CheckMenuElem (_("Display Automatic Regions"), mem_fun(*this, &Editor::toggle_show_auto_regions)));
448 // toggle_auto_regions_item = static_cast<CheckMenuItem*> (items.back());
449 // toggle_auto_regions_item->set_active (show_automatic_regions_in_region_list);
450 // items.push_back (SeparatorElem());
452 items.push_back (MenuElem (_("Import audio (copy)"), bind (mem_fun(*this, &Editor::import_audio), false)));
453 import_audio_item = items.back();
455 import_audio_item->set_sensitive (false);
457 items.push_back (MenuElem (_("Embed audio (link)"), mem_fun(*this, &Editor::embed_audio)));
458 embed_audio_item = items.back();
460 embed_audio_item->set_sensitive (false);
465 Editor::toggle_show_auto_regions ()
467 //show_automatic_regions_in_region_list = toggle_auto_regions_item->get_active();
468 show_automatic_regions_in_region_list = true;
469 redisplay_regions ();
473 Editor::toggle_full_region_list ()
475 region_list_display.freeze ();
476 if (toggle_full_region_list_item->get_active()) {
477 for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) {
478 r->expand_recursive ();
481 for (CTree_Helpers::RowIterator r = region_list_display.rows().begin(); r != region_list_display.rows().end(); ++r) {
485 region_list_display.thaw ();
489 Editor::region_list_display_key_press (GdkEventKey* ev)
495 Editor::region_list_display_key_release (GdkEventKey* ev)
497 switch (ev->keyval) {
499 remove_selected_regions_from_region_list ();
511 Editor::region_list_display_button_press (GdkEventButton *ev)
516 if (Keyboard::is_delete_event (ev)) {
517 if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
518 if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) {
525 if (Keyboard::is_context_menu_event (ev)) {
526 region_list_column_click (-1);
530 switch (ev->button) {
532 if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
533 if ((region = (AudioRegion *) region_list_display.row(row).get_data()) != 0) {
535 if (wave_cursor == 0) {
536 GdkPixmap *source, *mask;
537 GdkColor fg = { 0, 65535, 0, 0 }; /* Red. */
538 GdkColor bg = { 0, 0, 0, 65535 }; /* Blue. */
540 source = gdk_bitmap_create_from_data (NULL, wave_cursor_bits,
541 wave_cursor_width, wave_cursor_height);
542 mask = gdk_bitmap_create_from_data (NULL, wave_cursor_mask_bits,
543 wave_cursor_mask_width, wave_cursor_mask_height);
545 wave_cursor = gdk_cursor_new_from_pixmap (source,
551 gdk_pixmap_unref (source);
552 gdk_pixmap_unref (mask);
554 region_list_display_drag_region = region;
555 need_wave_cursor = 1;
557 /* audition on double click */
558 if (ev->type == GDK_2BUTTON_PRESS) {
559 consider_auditioning (region);
569 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
570 if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
571 if ((region = (AudioRegion *) region_list_display.get_row_data (row)) != 0) {
572 if (consider_auditioning (region)) {
573 region_list_display.row(row).select();
576 region_list_display.row(row).unselect();
583 /* to prevent regular selection -- i dont think this is needed JLC */
584 return stop_signal (region_list_display, "button_press_event");
597 Editor::region_list_display_button_release (GdkEventButton *ev)
601 if (region_list_display.get_selection_info ((int)ev->x, (int)ev->y, &row, &col) != 0) {
602 region_list_button_region = (AudioRegion *) region_list_display.get_row_data (row);
604 region_list_button_region = 0;
607 if (Keyboard::is_delete_event (ev)) {
608 remove_region_from_region_list ();
612 switch (ev->button) {
614 if (region_list_display_drag_region) {
615 insert_region_list_drag (*region_list_display_drag_region);
618 track_canvas_scroller.get_window().set_cursor (current_canvas_cursor);
619 region_list_display.get_window().set_cursor (0);
621 region_list_display_drag_region = 0;
622 need_wave_cursor = 0;
628 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
630 if (region_list_menu == 0) {
631 build_region_list_menu ();
636 if (region_list_display.selection().size() != 0) {
642 for (vector<MenuItem*>::iterator i = rl_context_menu_region_items.begin(); i != rl_context_menu_region_items.end(); ++i) {
643 (*i)->set_sensitive (sensitive);
646 region_list_menu->popup (0, 0);
658 Editor::region_list_display_motion (GdkEventMotion *ev)
660 if (need_wave_cursor == 1) {
661 track_canvas_scroller.get_window().set_cursor (wave_cursor);
662 region_list_display.get_window().set_cursor (wave_cursor);
664 need_wave_cursor = 2;
670 Editor::region_list_display_selected (gint row, gint col, GdkEvent *ev)
672 AudioRegion* region = static_cast<AudioRegion *>(region_list_display.get_row_data (row));
674 if (session == 0 || region == 0) {
678 set_selected_regionview_from_region_list (*region, false);
682 Editor::region_list_display_unselected (gint row, gint col, GdkEvent *ev)
687 Editor::consider_auditioning (AudioRegion *r)
690 session->cancel_audition ();
694 if (session->is_auditioning()) {
695 session->cancel_audition ();
696 if (r == last_audition_region) {
701 session->audition_region (*r);
702 last_audition_region = r;
708 Editor::region_list_display_enter_notify (GdkEventCrossing *ev)
710 ARDOUR_UI::instance()->allow_focus (true);
711 region_list_display.grab_focus ();
716 Editor::region_list_display_leave_notify (GdkEventCrossing *ev)
718 ARDOUR_UI::instance()->allow_focus (false);
723 Editor::_region_list_sorter (GtkCList* clist, gconstpointer a, gconstpointer b)
725 Editor* editor = static_cast<Editor*> (gtk_object_get_data (GTK_OBJECT(clist), "editor"));
726 return editor->region_list_sorter (a, b);
730 Editor::region_list_sorter (gconstpointer a, gconstpointer b)
732 GtkCListRow* row1 = (GtkCListRow *) a;
733 GtkCListRow* row2 = (GtkCListRow *) b;
735 AudioRegion* region1 = static_cast<AudioRegion*> (row1->data);
736 AudioRegion* region2 = static_cast<AudioRegion*> (row2->data);
738 if (region1 == 0 || region2 == 0) {
739 switch (region_list_sort_type) {
741 return true; /* XXX compare text in rows */
747 switch (region_list_sort_type) {
749 return strcasecmp (region1->name().c_str(), region2->name().c_str());
753 return region1->length() - region2->length();
757 return region1->position() - region2->position();
761 return region1->source().timestamp() - region2->source().timestamp();
765 return region1->start() - region2->start();
769 return (region1->start() + region1->length()) - (region2->start() + region2->length());
772 case BySourceFileName:
773 return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str());
776 case BySourceFileLength:
777 return region1->source().length() - region2->source().length();
780 case BySourceFileCreationDate:
781 return region1->source().timestamp() - region2->source().timestamp();
785 if (region1->source().name() == region2->source().name()) {
786 return strcasecmp (region1->name().c_str(), region2->name().c_str());
788 return strcasecmp (region1->source().name().c_str(), region2->source().name().c_str());
797 Editor::reset_region_list_sort_type (RegionListSortType type)
799 if (type != region_list_sort_type) {
800 region_list_sort_type = type;
804 region_list_display.set_column_title(0, _("Regions/name"));
808 region_list_display.set_column_title (0, _("Regions/length"));
812 region_list_display.set_column_title (0, _("Regions/position"));
816 region_list_display.set_column_title (0, _("Regions/creation"));
820 region_list_display.set_column_title (0, _("Regions/start"));
824 region_list_display.set_column_title (0, _("Regions/end"));
827 case BySourceFileName:
828 region_list_display.set_column_title (0, _("Regions/file name"));
831 case BySourceFileLength:
832 region_list_display.set_column_title (0, _("Regions/file size"));
835 case BySourceFileCreationDate:
836 region_list_display.set_column_title (0, _("Regions/file date"));
840 region_list_display.set_column_title (0, _("Regions/file system"));
844 region_list_display.sort ();
849 Editor::reset_region_list_sort_direction (bool up)
851 region_list_display.set_sort_type (up ? GTK_SORT_ASCENDING : GTK_SORT_DESCENDING);
852 region_list_display.sort ();
856 Editor::audition_region_from_region_list ()
858 if (region_list_button_region) {
859 consider_auditioning (dynamic_cast<AudioRegion*> (region_list_button_region));
864 Editor::hide_region_from_region_list ()
866 if (session == 0 || region_list_button_region == 0) {
870 region_list_button_region->set_hidden (true);
874 Editor::remove_region_from_region_list ()
876 if (session == 0 || region_list_button_region == 0) {
880 session->remove_region_from_region_list (*region_list_button_region);
884 Editor::remove_selected_regions_from_region_list ()
886 using namespace Gtk::CTree_Helpers;
887 SelectionList& selected = region_list_display.selection();
889 /* called from idle context to avoid snafus with the list
893 if (selected.empty() || session == 0) {
897 vector<Region*> to_be_deleted;
899 for (SelectionList::iterator i = selected.begin(); i != selected.end(); ++i) {
900 to_be_deleted.push_back (static_cast<Region*> ((*i).get_data()));
903 for (vector<Region*>::iterator i = to_be_deleted.begin(); i != to_be_deleted.end(); ++i) {
904 session->remove_region_from_region_list (**i);
911 Editor::region_list_display_drag_data_received (GdkDragContext *context,
914 GtkSelectionData *data,
918 vector<string> paths;
920 if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) {
921 do_embed_sndfiles (paths, false);
924 gtk_drag_finish (context, TRUE, FALSE, time);