X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_timefx.cc;h=765030507b649adaf16d916d36ca97fada65f1f8;hb=dfbc9da79aef9cc05808d29a20c6d12c5d553a80;hp=d40299a0a30579ce90a214e5931a903dbca84689;hpb=c0a009beb9471a92e83c641b2f5dcaeb613e97dc;p=ardour.git diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc index d40299a0a3..765030507b 100644 --- a/gtk2_ardour/editor_timefx.cc +++ b/gtk2_ardour/editor_timefx.cc @@ -21,8 +21,8 @@ #include #include #include - #include +#include #include "pbd/error.h" #include "pbd/pthread_utils.h" @@ -37,17 +37,15 @@ #include "region_selection.h" #include "time_fx_dialog.h" -#include "ardour/session.h" -#include "ardour/region.h" -#include "ardour/audioplaylist.h" -#include "ardour/audio_track.h" #include "ardour/audioregion.h" -#include "ardour/stretch.h" #include "ardour/midi_stretch.h" #include "ardour/pitch.h" +#include "ardour/region.h" +#include "ardour/session.h" +#include "ardour/stretch.h" #ifdef USE_RUBBERBAND -#include "rubberband/RubberBandStretcher.h" +#include using namespace RubberBand; #endif @@ -63,51 +61,104 @@ using namespace Gtkmm2ext; int Editor::time_stretch (RegionSelection& regions, float fraction) { - // FIXME: kludge, implement stretching of selection of both types + RegionList audio; + RegionList midi; + int aret; + + begin_reversible_command (_("stretch/shrink")); + + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + if ((*i)->region()->data_type() == DataType::AUDIO) { + audio.push_back ((*i)->region()); + } else if ((*i)->region()->data_type() == DataType::MIDI) { + midi.push_back ((*i)->region()); + } + } + + if ((aret = time_fx (audio, fraction, false)) != 0) { + return aret; + } + + set > midi_playlists_affected; + + for (RegionList::iterator i = midi.begin(); i != midi.end(); ++i) { + boost::shared_ptr playlist = (*i)->playlist(); + + if (playlist) { + playlist->clear_changes (); + } + + } + + ARDOUR::TimeFXRequest request; + request.time_fraction = fraction; + + for (RegionList::iterator i = midi.begin(); i != midi.end(); ++i) { + boost::shared_ptr playlist = (*i)->playlist(); + + if (!playlist) { + continue; + } + + MidiStretch stretch (*_session, request); + stretch.run (*i); - if (regions.front()->region()->data_type() == DataType::AUDIO) { - // Audio, pop up timefx dialog - return time_fx (regions, fraction, false); - } else { - // MIDI, just stretch - RouteTimeAxisView* rtv = dynamic_cast (®ions.front()->get_time_axis_view()); - if (!rtv) - return -1; - - boost::shared_ptr playlist - = rtv->track()->playlist(); - - ARDOUR::TimeFXRequest request; - request.time_fraction = fraction; - MidiStretch stretch(*_session, request); - begin_reversible_command ("midi stretch"); - stretch.run(regions.front()->region()); - playlist->clear_changes (); playlist->replace_region (regions.front()->region(), stretch.results[0], - regions.front()->region()->position()); - _session->add_command (new StatefulDiffCommand (playlist)); - commit_reversible_command (); + regions.front()->region()->position()); + midi_playlists_affected.insert (playlist); + } + + for (set >::iterator p = midi_playlists_affected.begin(); p != midi_playlists_affected.end(); ++p) { + _session->add_command (new StatefulDiffCommand (*p)); } + commit_reversible_command (); + return 0; } int Editor::pitch_shift (RegionSelection& regions, float fraction) { - return time_fx (regions, fraction, true); + RegionList rl; + + for (RegionSelection::iterator i = regions.begin(); i != regions.end(); ++i) { + rl.push_back ((*i)->region()); + } + + begin_reversible_command (_("pitch shift")); + + int ret = time_fx (rl, fraction, true); + + if (ret == 0) { + commit_reversible_command (); + } + + return ret; } -/** @return -1 in case of error, 1 if operation was cancelled by the user, 0 if everything went ok */ +/** @param val Percentage to time stretch by; ignored if pitch-shifting. + * @param pitching true to pitch shift, false to time stretch. + * @return -1 in case of error, 1 if operation was cancelled by the user, 0 if everything went ok */ int -Editor::time_fx (RegionSelection& regions, float val, bool pitching) +Editor::time_fx (RegionList& regions, float val, bool pitching) { delete current_timefx; - current_timefx = new TimeFXDialog (*this, pitching); + current_timefx->regions = regions; - current_timefx->progress_bar.set_fraction (0.0f); + /* See if we have any audio regions on our list */ + RegionList::iterator i = regions.begin (); + while (i != regions.end() && boost::dynamic_pointer_cast (*i) == 0) { + ++i; + } + if (i == regions.end ()) { + /* No audio regions; we can just do the timefx without a dialogue */ + do_timefx (); + return 0; + } + switch (current_timefx->run ()) { case RESPONSE_ACCEPT: break; @@ -117,7 +168,6 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) } current_timefx->status = 0; - current_timefx->regions = regions; if (pitching) { @@ -178,22 +228,22 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) break; } } - + switch (rb_current_opt) { case 0: - transients = NoTransients; peaklock = false; longwin = true; shortwin = false; + transients = NoTransients; peaklock = false; longwin = true; shortwin = false; break; case 1: - transients = NoTransients; peaklock = false; longwin = false; shortwin = false; + transients = NoTransients; peaklock = false; longwin = false; shortwin = false; break; case 2: - transients = NoTransients; peaklock = true; longwin = false; shortwin = false; + transients = NoTransients; peaklock = true; longwin = false; shortwin = false; break; case 3: - transients = BandLimitedTransients; peaklock = true; longwin = false; shortwin = false; + transients = BandLimitedTransients; peaklock = true; longwin = false; shortwin = false; break; case 5: - transients = Transients; peaklock = false; longwin = false; shortwin = true; + transients = Transients; peaklock = false; longwin = false; shortwin = true; break; case 6: transients = NoTransients; @@ -204,8 +254,8 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) // peaklock = false; break; default: - /* default/4 */ - transients = Transients; peaklock = true; longwin = false; shortwin = false; + /* default/4 */ + transients = Transients; peaklock = true; longwin = false; shortwin = false; break; }; @@ -233,7 +283,6 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) current_timefx->request.quick_seek = current_timefx->quick_button.get_active(); current_timefx->request.antialias = !current_timefx->antialias_button.get_active(); #endif - current_timefx->request.progress = 0.0f; current_timefx->request.done = false; current_timefx->request.cancel = false; @@ -255,77 +304,65 @@ Editor::time_fx (RegionSelection& regions, float val, bool pitching) pthread_detach (current_timefx->request.thread); - sigc::connection c = Glib::signal_timeout().connect (sigc::mem_fun (current_timefx, &TimeFXDialog::update_progress), 100); - while (!current_timefx->request.done && !current_timefx->request.cancel) { gtk_main_iteration (); } - c.disconnect (); + pthread_join (current_timefx->request.thread, 0); current_timefx->hide (); return current_timefx->status; } void -Editor::do_timefx (TimeFXDialog& dialog) +Editor::do_timefx () { - Track* t; boost::shared_ptr playlist; boost::shared_ptr new_region; - bool in_command = false; + set > playlists_affected; - for (RegionSelection::iterator i = dialog.regions.begin(); i != dialog.regions.end(); ) { - AudioRegionView* arv = dynamic_cast(*i); + uint32_t const N = current_timefx->regions.size (); - if (!arv) { - continue; - } - - boost::shared_ptr region (arv->audio_region()); - TimeAxisView* tv = &(arv->get_time_axis_view()); - RouteTimeAxisView* rtv; - RegionSelection::iterator tmp; - - tmp = i; - ++tmp; + for (RegionList::iterator i = current_timefx->regions.begin(); i != current_timefx->regions.end(); ++i) { + boost::shared_ptr playlist = (*i)->playlist(); - if ((rtv = dynamic_cast (tv)) == 0) { - i = tmp; - continue; + if (playlist) { + playlist->clear_changes (); } + } - if ((t = dynamic_cast (rtv->route().get())) == 0) { - i = tmp; - continue; - } + for (RegionList::iterator i = current_timefx->regions.begin(); i != current_timefx->regions.end(); ++i) { - if ((playlist = t->playlist()) == 0) { - i = tmp; + boost::shared_ptr region = boost::dynamic_pointer_cast (*i); + + if (!region || (playlist = region->playlist()) == 0) { continue; } - if (dialog.request.cancel) { + if (current_timefx->request.cancel) { /* we were cancelled */ - dialog.status = 1; + /* XXX what to do about playlists already affected ? */ + current_timefx->status = 1; return; } Filter* fx; - if (dialog.pitching) { - fx = new Pitch (*_session, dialog.request); + if (current_timefx->pitching) { + fx = new Pitch (*_session, current_timefx->request); } else { #ifdef USE_RUBBERBAND - fx = new RBStretch (*_session, dialog.request); + fx = new RBStretch (*_session, current_timefx->request); #else - fx = new STStretch (*_session, dialog.request); + fx = new STStretch (*_session, current_timefx->request); #endif } - if (fx->run (region)) { - dialog.status = -1; - dialog.request.done = true; + current_timefx->descend (1.0 / N); + + if (fx->run (region, current_timefx)) { + current_timefx->status = -1; + current_timefx->request.done = true; delete fx; return; } @@ -333,26 +370,20 @@ Editor::do_timefx (TimeFXDialog& dialog) if (!fx->results.empty()) { new_region = fx->results.front(); - if (!in_command) { - _session->begin_reversible_command (dialog.pitching ? _("pitch shift") : _("time stretch")); - in_command = true; - } - - playlist->clear_changes (); playlist->replace_region (region, new_region, region->position()); - _session->add_command (new StatefulDiffCommand (playlist)); + playlists_affected.insert (playlist); } - i = tmp; + current_timefx->ascend (); delete fx; } - if (in_command) { - _session->commit_reversible_command (); + for (set >::iterator p = playlists_affected.begin(); p != playlists_affected.end(); ++p) { + _session->add_command (new StatefulDiffCommand (*p)); } - dialog.status = 0; - dialog.request.done = true; + current_timefx->status = 0; + current_timefx->request.done = true; } void* @@ -364,16 +395,19 @@ Editor::timefx_thread (void *arg) pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0); - tsd->editor.do_timefx (*tsd); + tsd->editor.do_timefx (); /* GACK! HACK! sleep for a bit so that our request buffer for the GUI event loop doesn't die before any changes we made are processed by the GUI ... */ +#ifdef PLATFORM_WINDOWS + Glib::usleep(2 * G_USEC_PER_SEC); +#else struct timespec t = { 2, 0 }; nanosleep (&t, 0); - +#endif return 0; }