X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_region_list.cc;h=69a24b5c4c20f54a6f47cc661e87c8762f1c6134;hb=7e1b86aceeef477e13b4c35f524034d909acd92c;hp=1ebf59fecd1136b2a2064d21bf31f1f523a5f454;hpb=0c4c6e031a3624cfc74c2eef6e79527b7c49eca8;p=ardour.git diff --git a/gtk2_ardour/editor_region_list.cc b/gtk2_ardour/editor_region_list.cc index 1ebf59fecd..69a24b5c4c 100644 --- a/gtk2_ardour/editor_region_list.cc +++ b/gtk2_ardour/editor_region_list.cc @@ -15,29 +15,35 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id$ */ #include #include #include #include +#include #include #include -#include +#include +#include #include +#include + #include #include "editor.h" #include "editing.h" +#include "keyboard.h" #include "ardour_ui.h" #include "gui_thread.h" #include "actions.h" +#include "region_view.h" #include "utils.h" + #include "i18n.h" using namespace sigc; @@ -48,104 +54,152 @@ using namespace Glib; using namespace Editing; void -Editor::handle_audio_region_removed (boost::weak_ptr wregion) +Editor::handle_region_removed (boost::weak_ptr wregion) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_audio_region_removed), wregion)); + ENSURE_GUI_THREAD (mem_fun (*this, &Editor::redisplay_regions)); redisplay_regions (); } void -Editor::handle_new_audio_region (boost::weak_ptr wregion) +Editor::handle_new_regions (vector >& v) { - ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_audio_region), wregion)); - - /* don't copy region - the one we are being notified - about belongs to the session, and so it will - never be edited. - */ - - boost::shared_ptr region (wregion.lock()); - - if (region) { - add_audio_region_to_region_display (region); - } + ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_regions), v)); + add_regions_to_region_display (v); } void Editor::region_hidden (boost::shared_ptr r) { ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::region_hidden), r)); - redisplay_regions (); } void -Editor::add_audio_region_to_region_display (boost::shared_ptr region) +Editor::add_regions_to_region_display (vector >& regions) { + region_list_display.set_model (Glib::RefPtr(0)); + + for (vector >::iterator x = regions.begin(); x != regions.end(); ++x) { + boost::shared_ptr region ((*x).lock()); + if (region) { + add_region_to_region_display (region); + } + } + + region_list_display.set_model (region_list_model); +} + +void +Editor::add_region_to_region_display (boost::shared_ptr region) +{ + if (!region || !session) { + return; + } + string str; TreeModel::Row row; Gdk::Color c; + bool missing_source = boost::dynamic_pointer_cast(region->source()); if (!show_automatic_regions_in_region_list && region->automatic()) { return; } if (region->hidden()) { - TreeModel::iterator iter = region_list_model->get_iter ("0"); TreeModel::Row parent; TreeModel::Row child; - if (iter == region_list_model->children().end()) { - + if (!iter) { parent = *(region_list_model->append()); - parent[region_list_columns.name] = _("Hidden"); - /// XXX FIX ME parent[region_list_columns.region]->reset (); - + boost::shared_ptr proxy = parent[region_list_columns.region]; + proxy.reset (); } else { - if ((*iter)[region_list_columns.name] != _("Hidden")) { - parent = *(region_list_model->insert(iter)); parent[region_list_columns.name] = _("Hidden"); - /// XXX FIX ME parent[region_list_columns.region]->reset (); - + boost::shared_ptr proxy = parent[region_list_columns.region]; + proxy.reset (); } else { parent = *iter; } - } row = *(region_list_model->append (parent.children())); } else if (region->whole_file()) { + TreeModel::iterator i; + TreeModel::Children rows = region_list_model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + boost::shared_ptr rr = (*i)[region_list_columns.region]; + + if (rr && region->region_list_equivalent (rr)) { + return; + } + } + row = *(region_list_model->append()); - set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); + + if (missing_source) { + c.set_rgb(65535,0,0); // FIXME: error color from style + + } else if (region->automatic()){ + c.set_rgb(0,65535,0); // FIXME: error color from style + + } else { + set_color(c, rgba_from_style ("RegionListWholeFile", 0xff, 0, 0, 0, "fg", Gtk::STATE_NORMAL, false )); + + } + row[region_list_columns.color_] = c; if (region->source()->name()[0] == '/') { // external file - + if (region->whole_file()) { - str = ".../"; - str += PBD::basename_nosuffix (region->source()->name()); + boost::shared_ptr afs = boost::dynamic_pointer_cast(region->source()); + str = ".../"; + + if (afs) { + str = region_name_from_path (afs->path(), region->n_channels() > 1); + } else { + str += region->source()->name(); + } + } else { str = region->name(); } } else { - str = region->name(); + } + if (region->n_channels() > 1) { + std::stringstream foo; + foo << region->n_channels (); + str += " ["; + str += foo.str(); + str += ']'; } row[region_list_columns.name] = str; row[region_list_columns.region] = region; - - return; + if (missing_source) { + row[region_list_columns.path] = _("(MISSING) ") + region->source()->name(); + + } else { + row[region_list_columns.path] = region->source()->name(); + + } + + if (region->automatic()) { + return; + } + } else { /* find parent node, add as new child */ @@ -155,101 +209,560 @@ Editor::add_audio_region_to_region_display (boost::shared_ptr regio bool found_parent = false; for (i = rows.begin(); i != rows.end(); ++i) { - boost::shared_ptr rr = (*i)[region_list_columns.region]; boost::shared_ptr r = boost::dynamic_pointer_cast(rr); - + if (r && r->whole_file()) { + if (region->source_equivalent (r)) { row = *(region_list_model->append ((*i).children())); found_parent = true; break; } } - } + + TreeModel::iterator ii; + TreeModel::Children subrows = (*i).children(); - if (!found_parent) { - row = *(region_list_model->append()); - } + for (ii = subrows.begin(); ii != subrows.end(); ++ii) { + boost::shared_ptr rrr = (*ii)[region_list_columns.region]; + if (region->region_list_equivalent (rrr)) { + return; + + } + } + } + if (!found_parent) { + row = *(region_list_model->append()); + } } row[region_list_columns.region] = region; - if (region->n_channels() > 1) { - row[region_list_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels()); - } else { - row[region_list_columns.name] = region->name(); + populate_row(region, row); +} + + +void +Editor::region_list_region_changed (Change what_changed, boost::weak_ptr region) +{ + ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::region_list_region_changed), what_changed, region)); + + boost::shared_ptr r = region.lock (); + + if (!r) { + return; + } + + if (what_changed & ARDOUR::NameChanged) { + /* find the region in our model and change its name */ + TreeModel::Children rows = region_list_model->children (); + TreeModel::iterator i = rows.begin (); + while (i != rows.end ()) { + TreeModel::Children children = (*i)->children (); + TreeModel::iterator j = children.begin (); + while (j != children.end()) { + boost::shared_ptr c = (*j)[region_list_columns.region]; + if (c == r) { + break; + } + ++j; + } + + if (j != children.end()) { + (*j)[region_list_columns.name] = r->name (); + break; + } + + ++i; + } + } } void Editor::region_list_selection_changed() { - bool selected; - if (region_list_display.get_selection()->count_selected_rows() > 0) { - selected = true; + + TreeIter iter; + TreeView::Selection::ListHandle_Path rows = region_list_display.get_selection()->get_selected_rows (); + + deselect_all(); + + for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) { + + if (iter = region_list_model->get_iter (*i)) { // they could have clicked on a row that is just a placeholder, like "Hidden" + boost::shared_ptr region = (*iter)[region_list_columns.region]; + + if (region) { + + if (region->automatic()) { + region_list_display.get_selection()->unselect(*i); + + } else { + region_list_change_connection.block(true); + //editor_regions_selection_changed_connection.block(true); + + set_selected_regionview_from_region_list (region, Selection::Add); + + region_list_change_connection.block(false); + //editor_regions_selection_changed_connection.block(false); + } + } + } + } } else { - selected = false; + deselect_all(); } +} + +void +Editor::set_selected_in_region_list(RegionSelection& regions) +{ + for (RegionSelection::iterator iter = regions.begin(); iter != regions.end(); ++iter) { - if (selected) { - TreeView::Selection::ListHandle_Path rows = region_list_display.get_selection()->get_selected_rows (); - TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); - TreeIter iter; + TreeModel::iterator i; + TreeModel::Children rows = region_list_model->children(); + boost::shared_ptr r ((*iter)->region()); + + for (i = rows.begin(); i != rows.end(); ++i) { + + boost::shared_ptr compared_region = (*i)[region_list_columns.region]; - /* just set the first selected region (in fact, the selection model might be SINGLE, which - means there can only be one. - */ + if (r == compared_region) { + region_list_display.get_selection()->select(*i);; + break; + } + + if (!(*i).children().empty()) { + if (set_selected_in_region_list_subrow(r, (*i), 2)) { + break; + } + } + } + } +} + +bool +Editor::set_selected_in_region_list_subrow (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { - if ((iter = region_list_model->get_iter (*i))) { - set_selected_regionview_from_region_list (((*iter)[region_list_columns.region]), Selection::Set); + boost::shared_ptr compared_region = (*i)[region_list_columns.region]; + + if (region == compared_region) { + region_list_display.get_selection()->select(*i);; + return true; + } + + if (!(*i).children().empty()) { + if (update_region_subrows(region, (*i), level + 1)) { + return true; + } } } + return false; } void -Editor::insert_into_tmp_audio_regionlist(boost::shared_ptr region) +Editor::insert_into_tmp_regionlist(boost::shared_ptr region) { /* keep all whole files at the beginning */ if (region->whole_file()) { - tmp_audio_region_list.push_front (region); + tmp_region_list.push_front (region); } else { - tmp_audio_region_list.push_back (region); + tmp_region_list.push_back (region); } } void Editor::redisplay_regions () -{ - if (session) { +{ + if (no_region_list_redisplay || !session) { + return; + } + + bool tree_expanded = false; + + if (toggle_full_region_list_action && toggle_full_region_list_action->get_active()) { //If the list was expanded prior to rebuilding, + tree_expanded = true; //expand it again afterwards + } + + region_list_display.set_model (Glib::RefPtr(0)); + region_list_model->clear (); - region_list_display.set_model (Glib::RefPtr(0)); - region_list_model->clear (); + /* now add everything we have, via a temporary list used to help with + sorting. + */ + + tmp_region_list.clear(); + session->foreach_region (this, &Editor::insert_into_tmp_regionlist); + + for (list >::iterator r = tmp_region_list.begin(); r != tmp_region_list.end(); ++r) { + add_region_to_region_display (*r); + } + tmp_region_list.clear(); + + region_list_display.set_model (region_list_model); + + if (tree_expanded) { + region_list_display.expand_all(); + } +} - /* now add everything we have, via a temporary list used to help with - sorting. - */ +void +Editor::update_region_row (boost::shared_ptr region) +{ + if (!region || !session) { + return; + } + + TreeModel::iterator i; + TreeModel::Children rows = region_list_model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + +// cerr << "Level 1: Compare " << region->name() << " with parent " << (*i)[region_list_columns.name] << "\n"; - tmp_audio_region_list.clear(); - session->foreach_audio_region (this, &Editor::insert_into_tmp_audio_regionlist); + boost::shared_ptr compared_region = (*i)[region_list_columns.region]; + + if (region == compared_region) { +// cerr << "Matched\n"; + populate_row(region, (*i)); + return; + } + + if (!(*i).children().empty()) { + if (update_region_subrows(region, (*i), 2)) { + return; + } + } + } +// cerr << "Returning - No match\n"; +} + +bool +Editor::update_region_subrows (boost::shared_ptr region, TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { + +// cerr << "Level " << level << ": Compare " << region->name() << " with child " << (*i)[region_list_columns.name] << "\n"; + + boost::shared_ptr compared_region = (*i)[region_list_columns.region]; + + if (region == compared_region) { + populate_row(region, (*i)); +// cerr << "Matched\n"; + return true; + } + + if (!(*i).children().empty()) { + if (update_region_subrows(region, (*i), level + 1)) { + return true; + } + } + } + return false; +} + +void +Editor::update_all_region_rows () +{ + if (!session) { + return; + } - for (list >::iterator r = tmp_audio_region_list.begin(); r != tmp_audio_region_list.end(); ++r) { - add_audio_region_to_region_display (*r); + TreeModel::iterator i; + TreeModel::Children rows = region_list_model->children(); + + for (i = rows.begin(); i != rows.end(); ++i) { + + boost::shared_ptr region = (*i)[region_list_columns.region]; + + if (!region->automatic()) { + cerr << "level 1 : Updating " << region->name() << "\n"; + populate_row(region, (*i)); + } + + if (!(*i).children().empty()) { + update_all_region_subrows((*i), 2); } - tmp_audio_region_list.clear(); + } +} + +void +Editor::update_all_region_subrows (TreeModel::Row const &parent_row, int level) +{ + TreeModel::iterator i; + TreeModel::Children subrows = (*parent_row).children(); + + for (i = subrows.begin(); i != subrows.end(); ++i) { + + boost::shared_ptr region = (*i)[region_list_columns.region]; - region_list_display.set_model (region_list_model); + if (!region->automatic()) { + cerr << "level " << level << " : Updating " << region->name() << "\n"; + populate_row(region, (*i)); + } + + if (!(*i).children().empty()) { + update_all_region_subrows((*i), level + 1); + } } } void -Editor::region_list_clear () +Editor::populate_row (boost::shared_ptr region, TreeModel::Row const &row) { - region_list_model->clear(); + char start_str[16]; + char end_str[16]; + char length_str[16]; + char sync_str[16]; + char fadein_str[16]; + char fadeout_str[16]; + char used_str[8]; + int used; + BBT_Time bbt; // FIXME Why do these have to be declared here ? + SMPTE::Time smpte; // FIXME I would like them declared in the case statment where they are used. + + bool missing_source = boost::dynamic_pointer_cast(region->source()); + + boost::shared_ptr audioRegion = boost::dynamic_pointer_cast(region); + + bool fades_in_seconds = false; + + start_str[0] = '\0'; + end_str[0] = '\0'; + length_str[0] = '\0'; + sync_str[0] = '\0'; + fadein_str[0] = '\0'; + fadeout_str[0] = '\0'; + used_str[0] = '\0'; + + used = get_regionview_count_from_region_list(region); + sprintf (used_str, "%4d" , used); + + switch (ARDOUR_UI::instance()->secondary_clock.mode ()) { + case AudioClock::SMPTE: + case AudioClock::Off: /* If the secondary clock is off, default to SMPTE */ + session->smpte_time (region->position(), smpte); + sprintf (start_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + session->smpte_time (region->position() + region->length() - 1, smpte); + sprintf (end_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + session->smpte_time (region->length(), smpte); + sprintf (length_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + session->smpte_time (region->sync_position() + region->position(), smpte); + sprintf (sync_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + + if (audioRegion && !fades_in_seconds) { + session->smpte_time (audioRegion->fade_in()->back()->when, smpte); + sprintf (fadein_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + session->smpte_time (audioRegion->fade_out()->back()->when, smpte); + sprintf (fadeout_str, "%02d:%02d:%02d:%02d", smpte.hours, smpte.minutes, smpte.seconds, smpte.frames); + } + + break; + + case AudioClock::BBT: + session->tempo_map().bbt_time (region->position(), bbt); + sprintf (start_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + session->tempo_map().bbt_time (region->position() + region->length() - 1, bbt); + sprintf (end_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + session->tempo_map().bbt_time (region->length(), bbt); + sprintf (length_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + session->tempo_map().bbt_time (region->sync_position() + region->position(), bbt); + sprintf (sync_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + + if (audioRegion && !fades_in_seconds) { + session->tempo_map().bbt_time (audioRegion->fade_in()->back()->when, bbt); + sprintf (fadein_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + session->tempo_map().bbt_time (audioRegion->fade_out()->back()->when, bbt); + sprintf (fadeout_str, "%03d|%02d|%04d" , bbt.bars, bbt.beats, bbt.ticks); + } + break; + + case AudioClock::MinSec: + nframes_t left; + int hrs; + int mins; + float secs; + + left = region->position(); + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (start_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->position() + region->length() - 1; + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (end_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->length(); + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (length_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = region->sync_position() + region->position(); + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (sync_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + if (audioRegion && !fades_in_seconds) { + left = audioRegion->fade_in()->back()->when; + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (fadein_str, "%02d:%02d:%06.3f", hrs, mins, secs); + + left = audioRegion->fade_out()->back()->when; + hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f)); + left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f); + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + secs = left / (float) session->frame_rate(); + sprintf (fadeout_str, "%02d:%02d:%06.3f", hrs, mins, secs); + } + + break; + + case AudioClock::Frames: + snprintf (start_str, sizeof (start_str), "%u", region->position()); + snprintf (end_str, sizeof (end_str), "%u", (region->position() + region->length() - 1)); + snprintf (length_str, sizeof (length_str), "%u", region->length()); + snprintf (sync_str, sizeof (sync_str), "%u", region->sync_position() + region->position()); + + if (audioRegion && !fades_in_seconds) { + snprintf (fadein_str, sizeof (fadein_str), "%u", uint (audioRegion->fade_in()->back()->when)); + snprintf (fadeout_str, sizeof (fadeout_str), "%u", uint (audioRegion->fade_out()->back()->when)); + } + + break; + + default: + break; + } + + if (audioRegion && fades_in_seconds) { + + nframes_t left; + int mins; + int millisecs; + + left = audioRegion->fade_in()->back()->when; + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + millisecs = (int) floor ((left * 1000.0f) / session->frame_rate()); + + if (audioRegion->fade_in()->back()->when >= session->frame_rate()) { + sprintf (fadein_str, "%01dM %01dmS", mins, millisecs); + } else { + sprintf (fadein_str, "%01dmS", millisecs); + } + + left = audioRegion->fade_out()->back()->when; + mins = (int) floor (left / (session->frame_rate() * 60.0f)); + left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f); + millisecs = (int) floor ((left * 1000.0f) / session->frame_rate()); + + if (audioRegion->fade_out()->back()->when >= session->frame_rate()) { + sprintf (fadeout_str, "%01dM %01dmS", mins, millisecs); + } else { + sprintf (fadeout_str, "%01dmS", millisecs); + } + } + + if (used > 1) { + row[region_list_columns.start] = _("Multiple"); + row[region_list_columns.end] = _("Multiple"); + row[region_list_columns.sync] = _("Multiple"); + row[region_list_columns.fadein] = _("Multiple"); + row[region_list_columns.fadeout] = _("Multiple"); + row[region_list_columns.locked] = false; + row[region_list_columns.glued] = false; + row[region_list_columns.muted] = false; + row[region_list_columns.opaque] = false; + } else { + row[region_list_columns.start] = start_str; + row[region_list_columns.end] = end_str; + + if (region->sync_position() == region->position()) { + row[region_list_columns.sync] = _("Start"); + } else if (region->sync_position() == (region->position() + region->length() - 1)) { + row[region_list_columns.sync] = _("End"); + } else { + row[region_list_columns.sync] = sync_str; + } + + if (audioRegion) { + if (audioRegion->fade_in_active()) { + row[region_list_columns.fadein] = string_compose("%1%2%3", " ", fadein_str, " "); + } else { + row[region_list_columns.fadein] = string_compose("%1%2%3", "(", fadein_str, ")"); + } + } else { + row[region_list_columns.fadein] = ""; + } + + if (audioRegion) { + if (audioRegion->fade_out_active()) { + row[region_list_columns.fadeout] = string_compose("%1%2%3", " ", fadeout_str, " "); + } else { + row[region_list_columns.fadeout] = string_compose("%1%2%3", "(", fadeout_str, ")"); + } + } else { + row[region_list_columns.fadeout] = ""; + } + + row[region_list_columns.locked] = region->locked(); + + if (region->positional_lock_style() == Region::MusicTime) { + row[region_list_columns.glued] = true; + } else { + row[region_list_columns.glued] = false; + } + + row[region_list_columns.muted] = region->muted(); + row[region_list_columns.opaque] = region->opaque(); + } + + row[region_list_columns.length] = length_str; + row[region_list_columns.used] = used_str; + + if (missing_source) { + row[region_list_columns.path] = _("MISSING ") + region->source()->name(); + } else { + row[region_list_columns.path] = region->source()->name(); + } + + if (region->n_channels() > 1) { + row[region_list_columns.name] = string_compose("%1 [%2]", region->name(), region->n_channels()); + } else { + row[region_list_columns.name] = region->name(); + } } void @@ -342,32 +855,24 @@ Editor::region_list_display_button_press (GdkEventButton *ev) } } - if (region == 0) { - return false; - } - - if (Keyboard::is_delete_event (ev)) { - session->remove_region_from_region_list (region); - return true; - } - if (Keyboard::is_context_menu_event (ev)) { show_region_list_display_context_menu (ev->button, ev->time); return true; } + if (region == 0) { + region_list_display.get_selection()->unselect_all(); + deselect_all(); + return false; + } + switch (ev->button) { case 1: - /* audition on double click */ - if (ev->type == GDK_2BUTTON_PRESS) { - consider_auditioning (region); - return true; - } - return false; break; case 2: - if (!Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) { + // audition on middle click (stop audition too) + if (!Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { consider_auditioning (region); } return true; @@ -544,7 +1049,16 @@ Editor::region_list_selection_mapover (slot > sl) TreeIter iter; if ((iter = region_list_model->get_iter (*i))) { - sl (((*iter)[region_list_columns.region])); + + /* some rows don't have a region associated with them, but can still be + selected (XXX maybe prevent them from being selected) + */ + + boost::shared_ptr r = (*iter)[region_list_columns.region]; + + if (r) { + sl (r); + } } } } @@ -581,15 +1095,24 @@ Editor::remove_region_from_region_list () void Editor::region_list_display_drag_data_received (const RefPtr& context, - int x, int y, - const SelectionData& data, - guint info, guint time) + int x, int y, + const SelectionData& data, + guint info, guint time) { vector paths; + if (data.get_target() == "GTK_TREE_MODEL_ROW") { + region_list_display.on_drag_data_received (context, x, y, data, info, time); + return; + } + if (convert_drop_to_paths (paths, context, x, y, data, info, time) == 0) { - nframes_t pos = 0; - do_embed (paths, false, ImportAsRegion, 0, pos, true); + nframes64_t pos = 0; + if (Profile->get_sae() || Config->get_only_copy_imported_files()) { + do_import (paths, Editing::ImportDistinctFiles, Editing::ImportAsRegion, SrcBest, pos); + } else { + do_embed (paths, Editing::ImportDistinctFiles, ImportAsRegion, pos); + } context->drag_finish (true, false, time); } } @@ -598,8 +1121,42 @@ bool Editor::region_list_selection_filter (const RefPtr& model, const TreeModel::Path& path, bool yn) { /* not possible to select rows that do not represent regions, like "Hidden" */ + + TreeModel::iterator iter = model->get_iter (path); + + if (iter) { + boost::shared_ptr r =(*iter)[region_list_columns.region]; + if (!r) { + return false; + } + } - /// XXXX FIXME boost::shared_ptr r = ((model->get_iter (path)))[region_list_columns.region]; - /// return r != 0; return true; } + +void +Editor::region_name_edit (const Glib::ustring& path, const Glib::ustring& new_text) +{ + boost::shared_ptr region; + TreeIter iter; + + if ((iter = region_list_model->get_iter (path))) { + region = (*iter)[region_list_columns.region]; + (*iter)[region_list_columns.name] = new_text; + } + + /* now mapover everything */ + + if (region) { + vector equivalents; + get_regions_corresponding_to (region, equivalents); + + for (vector::iterator i = equivalents.begin(); i != equivalents.end(); ++i) { + if (new_text != (*i)->region()->name()) { + (*i)->region()->set_name (new_text); + } + } + } + +} +