1578
1608
boost::shared_ptr<Playlist> pl;
1580
1610
if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1581
Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
1582
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1583
add_region_context_items (atv->audio_view(), (*i), edit_items);
1611
Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed()));
1613
if (selection->regions.size() > 1) {
1614
// there's already a multiple selection: just add a
1615
// single region context menu that will act on all
1617
boost::shared_ptr<Region> dummy_region; // = NULL
1618
add_region_context_items (atv->audio_view(), dummy_region, edit_items);
1620
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1621
add_region_context_items (atv->audio_view(), (*i), edit_items);
1585
1625
delete regions;
1618
1658
add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
1621
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1622
add_region_context_items (atv->audio_view(), (*i), edit_items);
1661
if (selection->regions.size() > 1) {
1662
// there's already a multiple selection: just add a
1663
// single region context menu that will act on all
1665
boost::shared_ptr<Region> dummy_region; // = NULL
1666
add_region_context_items (atv->audio_view(), dummy_region, edit_items);
1668
for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1669
add_region_context_items (atv->audio_view(), (*i), edit_items);
1625
1672
delete regions;
1756
1803
ar = boost::dynamic_pointer_cast<AudioRegion> (region);
1805
/* when this particular menu pops up, make the relevant region
1809
region_menu->signal_map_event().connect (
1811
mem_fun(*this, &Editor::set_selected_regionview_from_map_event),
1813
boost::weak_ptr<Region>(region)
1817
items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
1818
items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1759
/* when this particular menu pops up, make the relevant region
1763
region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
1765
items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
1766
items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1767
1821
items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1768
1822
items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1769
1823
items.push_back (SeparatorElem());
1784
1838
sigc::connection fooc;
1786
items.push_back (CheckMenuElem (_("Lock")));
1787
CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
1788
if (region->locked()) {
1789
region_lock_item->set_active();
1791
region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
1793
items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
1794
CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
1796
switch (region->positional_lock_style()) {
1797
case Region::MusicTime:
1798
bbt_glue_item->set_active (true);
1801
bbt_glue_item->set_active (false);
1805
bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
1807
items.push_back (CheckMenuElem (_("Mute")));
1808
CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
1809
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
1810
if (region->muted()) {
1812
region_mute_item->set_active();
1816
if (!Profile->get_sae()) {
1817
items.push_back (CheckMenuElem (_("Opaque")));
1818
CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
1819
fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
1820
if (region->opaque()) {
1841
items.push_back (CheckMenuElem (_("Lock")));
1842
CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
1843
if (region->locked()) {
1844
region_lock_item->set_active();
1846
region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
1848
items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
1849
CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
1851
switch (region->positional_lock_style()) {
1852
case Region::MusicTime:
1853
bbt_glue_item->set_active (true);
1856
bbt_glue_item->set_active (false);
1860
bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
1862
items.push_back (CheckMenuElem (_("Mute")));
1863
CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
1864
fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
1865
if (region->muted()) {
1821
1866
fooc.block (true);
1822
region_opaque_item->set_active();
1867
region_mute_item->set_active();
1823
1868
fooc.block (false);
1871
if (!Profile->get_sae()) {
1872
items.push_back (CheckMenuElem (_("Opaque")));
1873
CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
1874
fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
1875
if (region->opaque()) {
1877
region_opaque_item->set_active();
1882
// multiple regions selected
1883
// how should these act?
1884
// here they toggle the property of all selected regions
1886
items.push_back (MenuElem (_("Lock"), mem_fun(*this, &Editor::toggle_region_lock)));
1887
items.push_back (MenuElem (_("Mute"), mem_fun(*this, &Editor::toggle_region_mute)));
1888
if (!Profile->get_sae()) {
1889
items.push_back (MenuElem (_("Opaque"), mem_fun(*this, &Editor::toggle_region_opaque)));
1827
1893
items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1828
if (region->at_natural_position()) {
1894
if (region && region->at_natural_position()) {
1829
1895
items.back().set_sensitive (false);
1971
2037
items.push_back (MenuElem (_("Duplicate range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1972
2038
items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::create_named_selection)));
1973
2039
items.push_back (SeparatorElem());
1974
items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2040
items.push_back (MenuElem (_("Consolidate range"), bind (mem_fun(*this, &Editor::bounce_range_selection), true)));
2041
items.push_back (MenuElem (_("Bounce range to region list"), bind (mem_fun(*this, &Editor::bounce_range_selection), false)));
1975
2042
items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
2512
2579
switch (snap_type) {
2513
2580
case SnapToCDFrame:
2514
2581
if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2515
start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2582
start = (nframes64_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2517
start = (nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2584
start = (nframes64_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2521
2588
case SnapToSMPTEFrame:
2522
2589
if (((direction == 0) && (fmod((double)start, (double)session->frames_per_smpte_frame()) > (session->frames_per_smpte_frame() / 2))) || (direction > 0)) {
2523
start = (nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2590
start = (nframes64_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2525
start = (nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2592
start = (nframes64_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
4096
Editor::reposition_and_zoom (nframes_t frame, double fpu)
4172
Editor::reposition_and_zoom (nframes64_t frame, double fpu)
4174
//cerr << "Editor::reposition_and_zoom () called ha v:l:u:ps:fpu = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << frames_per_unit << endl;//DEBUG
4098
4175
reset_x_origin (frame);
4099
4176
reset_zoom (fpu);
4178
if (!no_save_visual) {
4179
undo_visual_stack.push_back (current_visual_state(false));
4183
Editor::VisualState*
4184
Editor::current_visual_state (bool with_tracks)
4186
VisualState* vs = new VisualState;
4187
vs->y_position = vertical_adjustment.get_value();
4188
vs->frames_per_unit = frames_per_unit;
4189
vs->leftmost_frame = leftmost_frame;
4190
vs->zoom_focus = zoom_focus;
4191
vs->zoomed_to_region = zoomed_to_region;
4194
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4195
vs->track_states.push_back (TAVState ((*i), &(*i)->get_state()));
4203
Editor::undo_visual_state ()
4205
if (undo_visual_stack.empty()) {
4209
VisualState* vs = undo_visual_stack.back();
4210
undo_visual_stack.pop_back();
4211
use_visual_state (*vs);
4212
redo_visual_stack.push_back (vs);
4216
Editor::redo_visual_state ()
4218
if (redo_visual_stack.empty()) {
4222
VisualState* vs = redo_visual_stack.back();
4223
redo_visual_stack.pop_back();
4224
use_visual_state (*vs);
4225
undo_visual_stack.push_back (vs);
4103
4229
Editor::swap_visual_state ()
4105
if (last_visual_state.frames_per_unit == 0) {
4110
/* note: the correct functionality here is very dependent on the ordering of
4111
setting zoom focus, horizontal position and finally zoom. this is because
4112
it is set_frames_per_unit() that overwrites last_visual_state.
4115
set_zoom_focus (last_visual_state.zoom_focus);
4116
reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit);
4117
zoomed_to_region = false;
4231
if (undo_visual_stack.empty()) {
4232
redo_visual_state ();
4234
undo_visual_state ();
4239
Editor::use_visual_state (VisualState& vs)
4241
no_save_visual = true;
4243
vertical_adjustment.set_value (vs.y_position);
4245
set_zoom_focus (vs.zoom_focus);
4246
reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit);
4248
for (list<TAVState>::iterator i = vs.track_states.begin(); i != vs.track_states.end(); ++i) {
4249
TrackViewList::iterator t;
4251
/* check if the track still exists - it could have been deleted */
4253
if ((t = find (track_views.begin(), track_views.end(), i->first)) != track_views.end()) {
4254
(*t)->set_state (*(i->second));
4258
if (!vs.track_states.empty()) {
4259
update_route_visibility ();
4262
no_save_visual = false;
4229
4376
if (p & VisualChange::TimeOrigin) {
4231
nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
4378
nframes64_t time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
4380
/* if we seek beyond the current end of the canvas, move the end */
4233
4382
if (time_origin != pending_visual_change.time_origin) {
4384
if (horizontal_adjustment.get_upper() < pending_visual_change.time_origin) {
4385
last_canvas_frame = (cef > (pending_visual_change.time_origin + current_page_frames())) ? cef : pending_visual_change.time_origin + current_page_frames();
4386
horizontal_adjustment.set_upper ((cef - csf) / frames_per_unit);
4387
reset_scrolling_region ();
4234
4390
horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
4236
4392
update_fixed_rulers();
4237
4393
redisplay_tempo (true);
4396
//cerr << "Editor::idle_visual_changer () called ha v:l:u:ps:fpu = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << frames_per_unit << endl;//DEBUG
4241
4397
return 0; /* this is always a one-shot call */
4568
4724
_have_idled = true;
4728
Editor::start_resize_line_ops ()
4731
old_resize_line_y = -1;
4733
need_resize_line = true;
4738
Editor::end_resize_line_ops ()
4741
need_resize_line = false;
4743
if (old_resize_line_y >= 0) {
4744
Gdk::Rectangle r (0, old_resize_line_y, (int) canvas_width, 3);
4745
Glib::RefPtr<Gdk::Window> win = get_window();
4746
cerr << "Final invalidation at " << old_resize_line_y << endl;
4747
win->invalidate_rect (r, false);
4753
Editor::queue_draw_resize_line (int at)
4756
Glib::RefPtr<Gdk::Window> win = get_window();
4760
if (win && canvas_width) {
4762
int controls_width = controls_layout.get_width();
4765
controls_layout.get_window()->get_origin (xroot, discard);
4767
if (old_resize_line_y >= 0) {
4769
/* redraw where it used to be */
4772
Gdk::Rectangle r (xroot, old_resize_line_y - 1, controls_width + (int) canvas_width, 3);
4773
win->invalidate_rect (r, true);
4774
cerr << "invalidate " << xroot << "," << old_resize_line_y - 1 << ' '
4775
<< controls_width + canvas_width << " x 3\n";
4778
/* draw where it is */
4780
Gdk::Rectangle r (xroot, at - 1, controls_width + (int) canvas_width, 3);
4781
win->invalidate_rect (r, true);
4787
Editor::on_expose_event (GdkEventExpose* ev)
4789
/* cerr << "+++ editor expose "
4790
<< ev->area.x << ',' << ev->area.y
4792
<< ev->area.width << " x " << ev->area.height
4793
<< " need reize ? " << need_resize_line
4796
bool ret = Window::on_expose_event (ev);
4799
if (need_resize_line) {
4801
int xroot, yroot, discard;
4804
/* Our root coordinates for drawing the line will be the left edge
4805
of the track controls, and the upper left edge of our own window.
4808
get_window()->get_origin (discard, yroot);
4809
controls_layout.get_window()->get_origin (xroot, discard);
4810
controls_width = controls_layout.get_width();
4813
GdkRectangle intersection;
4816
lr.y = resize_line_y;
4817
lr.width = controls_width + (int) canvas_width;
4820
if (gdk_rectangle_intersect (&lr, &ev->area, &intersection)) {
4822
Glib::RefPtr<Gtk::Style> style (get_style());
4823
Glib::RefPtr<Gdk::GC> black_gc (style->get_black_gc ());
4824
Glib::RefPtr<Gdk::GC> gc = wrap (black_gc->gobj_copy(), false);
4826
/* draw on root window */
4828
GdkWindow* win = gdk_get_default_root_window();
4830
gc->set_subwindow (Gdk::INCLUDE_INFERIORS);
4831
gc->set_line_attributes (3, Gdk::LINE_SOLID,
4835
gdk_draw_line (win, gc->gobj(),
4837
yroot + resize_line_y,
4838
xroot + (int) canvas_width + controls_width,
4839
yroot + resize_line_y);
4840
cerr << "drew line @ " << xroot << ", " << yroot + resize_line_y
4841
<< " to " << xroot + (int) canvas_width + controls_width
4842
<< ", " << yroot + resize_line_y
4844
old_resize_line_y = yroot + resize_line_y;
4845
cerr << "NEXT EXPOSE SHOULD BE AT " << old_resize_line_y << endl;
4847
cerr << "no intersect with "
4848
<< lr.x << ',' << lr.y
4850
<< lr.width << " x " << lr.height
4855
//cerr << "--- editor expose\n";
4862
_idle_resizer (gpointer arg)
4864
return ((Editor*)arg)->idle_resize ();
4868
Editor::add_to_idle_resize (TimeAxisView* view, uint32_t h)
4870
if (resize_idle_id < 0) {
4871
resize_idle_id = g_idle_add (_idle_resizer, this);
4874
resize_idle_target = h;
4876
pending_resizes.push_back (view);
4878
if (!selection->tracks.empty()) {
4879
pending_resizes.insert (pending_resizes.end(), selection->tracks.begin(), selection->tracks.end());
4884
Editor::idle_resize ()
4886
for (vector<TimeAxisView*>::iterator i = pending_resizes.begin(); i != pending_resizes.end(); ++i) {
4887
(*i)->idle_resize (resize_idle_target);
4889
pending_resizes.clear();
4890
resize_idle_id = -1;