add_item(index = new AssetPopupBuildIndex(mwindow, this));
add_item(view = new AssetPopupView(mwindow, this));
add_item(view_window = new AssetPopupViewWindow(mwindow, this));
- add_item(mixer = new AssetPopupMixer(mwindow, this));
+ add_item(open_mixer = new AssetPopupOpenMixer(mwindow, this));
+ add_item(insert_mixer = new AssetPopupInsertMixer(mwindow, this));
add_item(new AssetPopupPaste(mwindow, this));
add_item(menu_item = new BC_MenuItem(_("Match...")));
menu_item->add_submenu(submenu = new BC_SubMenu());
return 1;
}
-AssetPopupMixer::AssetPopupMixer(MWindow *mwindow, AssetPopup *popup)
+AssetPopupOpenMixer::AssetPopupOpenMixer(MWindow *mwindow, AssetPopup *popup)
: BC_MenuItem(_("Open Mixers"))
{
this->mwindow = mwindow;
this->popup = popup;
}
-AssetPopupMixer::~AssetPopupMixer()
+AssetPopupOpenMixer::~AssetPopupOpenMixer()
{
}
-int AssetPopupMixer::handle_event()
+int AssetPopupOpenMixer::handle_event()
{
- mwindow->gui->lock_window("AssetPopupMixer::handle_event");
+ mwindow->gui->lock_window("AssetPopupOpenMixer::handle_event");
mwindow->create_mixers();
mwindow->gui->unlock_window();
return 1;
}
+AssetPopupInsertMixer::AssetPopupInsertMixer(MWindow *mwindow, AssetPopup *popup)
+ : BC_MenuItem(_("Insert Mixers"))
+{
+ this->mwindow = mwindow;
+ this->popup = popup;
+}
+
+AssetPopupInsertMixer::~AssetPopupInsertMixer()
+{
+}
+
+int AssetPopupInsertMixer::handle_event()
+{
+ mwindow->gui->lock_window("AssetPopupInsertMixer::handle_event");
+ mwindow->create_mixers(-1);
+ mwindow->gui->unlock_window();
+ return 1;
+}
+
AssetPopupPaste::AssetPopupPaste(MWindow *mwindow, AssetPopup *popup)
: BC_MenuItem(_("Paste"))
{
AssetPopupBuildIndex *index;
AssetPopupView *view;
AssetPopupViewWindow *view_window;
- AssetPopupMixer *mixer;
+ AssetPopupOpenMixer *open_mixer;
+ AssetPopupInsertMixer *insert_mixer;
AWindowListFormat *format;
};
AssetPopup *popup;
};
-class AssetPopupMixer : public BC_MenuItem
+class AssetPopupOpenMixer : public BC_MenuItem
{
public:
- AssetPopupMixer(MWindow *mwindow, AssetPopup *popup);
- ~AssetPopupMixer();
+ AssetPopupOpenMixer(MWindow *mwindow, AssetPopup *popup);
+ ~AssetPopupOpenMixer();
+
+ int handle_event();
+
+ MWindow *mwindow;
+ AssetPopup *popup;
+};
+
+class AssetPopupInsertMixer : public BC_MenuItem
+{
+public:
+ AssetPopupInsertMixer(MWindow *mwindow, AssetPopup *popup);
+ ~AssetPopupInsertMixer();
int handle_event();
class AssetPopupBuildIndex;
class AssetPopupView;
class AssetPopupViewWindow;
-class AssetPopupMixer;
+class AssetPopupOpenMixer;
+class AssetPopupInsertMixer;
class AssetPopupPaste;
class AssetMatchSize;
class AssetMatchRate;
}
}
+// trim edits before position 0
+ while( first && first->startproject+first->length < 0 )
+ delete first;
+ if( first && first->startproject < 0 ) {
+ first->length += first->startproject;
+ first->startproject = 0;
+ }
+
// Insert silence between edits which aren't consecutive
for(current = last; current; current = current->previous)
{
#include "floatauto.h"
#include "floatautos.h"
#include "guicast.h"
+#include "keyframe.h"
+#include "keyframes.h"
#include "indexstate.h"
#include "interlacemodes.h"
#include "labels.h"
return new_position;
}
+double EDL::skip_silence(double position)
+{
+ double result = position, nearest = DBL_MAX;
+ for( Track *track=tracks->first; track; track=track->next ) {
+ if( !track->play ) continue;
+ Edit *edit = track->edits->editof(position, PLAY_FORWARD, 0);
+ while( edit && edit->silence() ) edit = edit->next;
+ if( !edit ) continue;
+ double pos = track->from_units(edit->startproject);
+ if( pos > position && pos < nearest )
+ nearest = result = pos;
+ }
+ return result;
+}
+
void EDL::rescale_proxy(int orig_scale, int new_scale)
{
if( orig_scale == new_scale ) return;
return new_groups.size();
}
+EDL *EDL::selected_edits_to_clip(int packed,
+ double *start_position, Track **start_track,
+ int edit_labels, int edit_autos, int edit_plugins)
+{
+ double start = DBL_MAX, end = DBL_MIN;
+ Track *first_track=0, *last_track = 0;
+ for( Track *track=tracks->first; track; track=track->next ) {
+ if( !track->record ) continue;
+ int empty = 1;
+ for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
+ if( !edit->is_selected || edit->silence() ) continue;
+ double edit_pos = track->from_units(edit->startproject);
+ if( start > edit_pos ) start = edit_pos;
+ if( end < (edit_pos+=edit->length) ) end = edit_pos;
+ empty = 0;
+ }
+ if( empty ) continue;
+ if( !first_track ) first_track = track;
+ last_track = track;
+ }
+ if( start_position ) *start_position = start;
+ if( start_track ) *start_track = first_track;
+ if( !first_track ) return 0;
+ EDL *new_edl = new EDL();
+ new_edl->create_objects();
+ new_edl->copy_session(this);
+ const char *text = _("new_edl edit");
+ new_edl->set_path(text);
+ strcpy(new_edl->local_session->clip_title, text);
+ strcpy(new_edl->local_session->clip_notes, text);
+ new_edl->session->video_tracks = 0;
+ new_edl->session->audio_tracks = 0;
+ for( Track *track=tracks->first; track; track=track->next ) {
+ if( !track->record ) continue;
+ if( first_track ) {
+ if( first_track != track ) continue;
+ first_track = 0;
+ }
+ Track *new_track = 0;
+ if( !packed )
+ new_track = new_edl->add_new_track(track->data_type);
+ int64_t start_pos = track->to_units(start, 0);
+ int64_t end_pos = track->to_units(end, 0);
+ int64_t startproject = 0;
+ Edit *edit = track->edits->first;
+ for( ; edit; edit=edit->next ) {
+ if( !edit->is_selected || edit->silence() ) continue;
+ if( edit->startproject < start_pos ) continue;
+ if( edit->startproject >= end_pos ) break;
+ int64_t edit_start_pos = edit->startproject;
+ int64_t edit_end_pos = edit->startproject + edit->length;
+ if( !new_track )
+ new_track = new_edl->add_new_track(track->data_type);
+ int64_t edit_pos = edit_start_pos - start_pos;
+ if( !packed && edit_pos > startproject ) {
+ Edit *silence = new Edit(new_edl, new_track);
+ silence->startproject = startproject;
+ silence->length = edit_pos - startproject;
+ new_track->edits->append(silence);
+ startproject = edit_pos;
+ }
+ int64_t clip_start_pos = startproject;
+ Edit *clip_edit = new Edit(new_edl, new_track);
+ clip_edit->copy_from(edit);
+ clip_edit->startproject = startproject;
+ startproject += clip_edit->length;
+ new_track->edits->append(clip_edit);
+ if( edit_labels ) {
+ double edit_start = track->from_units(edit_start_pos);
+ double edit_end = track->from_units(edit_end_pos);
+ double clip_start = new_track->from_units(clip_start_pos);
+ Label *label = labels->first;
+ for( ; label; label=label->next ) {
+ if( label->position < edit_start ) continue;
+ if( label->position >= edit_end ) break;
+ double clip_position = label->position - edit_start + clip_start;
+ Label *clip_label = new_edl->labels->first;
+ while( clip_label && clip_label->position<clip_position )
+ clip_label = clip_label->next;
+ if( clip_label && clip_label->position == clip_position ) continue;
+ Label *new_label = new Label(new_edl,
+ new_edl->labels, clip_position, label->textstr);
+ new_edl->labels->insert_before(clip_label, new_label);
+ }
+ }
+ if( edit_autos ) {
+ Automation *automation = track->automation;
+ Automation *new_automation = new_track->automation;
+ for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
+ Autos *autos = automation->autos[i];
+ if( !autos ) continue;
+ Autos *new_autos = new_automation->autos[i];
+ new_autos->default_auto->copy_from(autos->default_auto);
+ Auto *aut0 = autos->first;
+ for( ; aut0; aut0=aut0->next ) {
+ if( aut0->position < edit_start_pos ) continue;
+ if( aut0->position >= edit_end_pos ) break;
+ Auto *new_auto = new_autos->new_auto();
+ new_auto->copy_from(aut0);
+ int64_t clip_position = aut0->position - edit_start_pos + clip_start_pos;
+ new_auto->position = clip_position;
+ new_autos->append(new_auto);
+ }
+ }
+ }
+ if( edit_plugins ) {
+ while( new_track->plugin_set.size() < track->plugin_set.size() )
+ new_track->plugin_set.append(0);
+ for( int i=0; i<track->plugin_set.total; ++i ) {
+ PluginSet *plugin_set = track->plugin_set[i];
+ if( !plugin_set ) continue;
+ PluginSet *new_plugin_set = new_track->plugin_set[i];
+ if( !new_plugin_set ) {
+ new_plugin_set = new PluginSet(new_edl, new_track);
+ new_track->plugin_set[i] = new_plugin_set;
+ }
+ Plugin *plugin = (Plugin*)plugin_set->first;
+ int64_t startplugin = new_plugin_set->length();
+ for( ; plugin ; plugin=(Plugin*)plugin->next ) {
+ if( plugin->silence() ) continue;
+ int64_t plugin_start_pos = plugin->startproject;
+ int64_t plugin_end_pos = plugin_start_pos + plugin->length;
+ if( plugin_end_pos < start_pos ) continue;
+ if( plugin_start_pos > end_pos ) break;
+ if( plugin_start_pos < edit_start_pos )
+ plugin_start_pos = edit_start_pos;
+ if( plugin_end_pos > edit_end_pos )
+ plugin_end_pos = edit_end_pos;
+ if( plugin_start_pos >= plugin_end_pos ) continue;
+ int64_t plugin_pos = plugin_start_pos - start_pos;
+ if( !packed && plugin_pos > startplugin ) {
+ Plugin *silence = new Plugin(new_edl, new_track, "");
+ silence->startproject = startplugin;
+ silence->length = plugin_pos - startplugin;
+ new_plugin_set->append(silence);
+ startplugin = plugin_pos;
+ }
+ Plugin *new_plugin = new Plugin(new_edl, new_track, plugin->title);
+ new_plugin->copy_base(plugin);
+ new_plugin->startproject = startplugin;
+ new_plugin->length = plugin_end_pos - plugin_start_pos;
+ startplugin += new_plugin->length;
+ new_plugin_set->append(new_plugin);
+ KeyFrames *keyframes = plugin->keyframes;
+ KeyFrames *new_keyframes = new_plugin->keyframes;
+ new_keyframes->default_auto->copy_from(keyframes->default_auto);
+ new_keyframes->default_auto->position = new_plugin->startproject;
+ KeyFrame *keyframe = (KeyFrame*)keyframes->first;
+ for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
+ if( keyframe->position < edit_start_pos ) continue;
+ if( keyframe->position >= edit_end_pos ) break;
+ KeyFrame *clip_keyframe = new KeyFrame(new_edl, new_keyframes);
+ clip_keyframe->copy_from(keyframe);
+ int64_t key_position = keyframe->position - start_pos;
+ if( packed )
+ key_position += new_plugin->startproject - plugin_pos;
+ clip_keyframe->position = key_position;
+ new_keyframes->append(clip_keyframe);
+ }
+ }
+ }
+ }
+ }
+ if( last_track == track ) break;
+ }
+ return new_edl;
+}
+
+EDL *EDL::selected_edits_to_clip(int packed, double *start_position, Track **start_track)
+{
+ return selected_edits_to_clip(packed, start_position, start_track,
+ session->labels_follow_edits,
+ session->autos_follow_edits,
+ session->plugins_follow_edits);
+}
+
+void EDL::paste_edits(EDL *clip, Track *first_track, double position, int overwrite,
+ int edit_edits, int edit_labels, int edit_autos, int edit_plugins)
+{
+ if( !first_track )
+ first_track = tracks->first;
+ Track *src = clip->tracks->first;
+ for( Track *track=first_track; track && src; track=track->next ) {
+ if( !track->record ) continue;
+ int64_t pos = track->to_units(position, 0);
+ if( edit_edits ) {
+ for( Edit *edit=src->edits->first; edit; edit=edit->next ) {
+ if( edit->silence() ) continue;
+ int64_t start = pos + edit->startproject;
+ int64_t len = edit->length, end = start + len;
+ if( overwrite )
+ track->edits->clear(start, end);
+ Edit *dst = track->edits->insert_new_edit(start);
+ dst->copy_from(edit);
+ dst->startproject = start;
+ dst->is_selected = 1;
+ while( (dst=dst->next) != 0 )
+ dst->startproject += edit->length;
+ if( overwrite ) continue;
+ if( edit_labels && track == first_track ) {
+ double dst_pos = track->from_units(start);
+ double dst_len = track->from_units(len);
+ for( Label *label=labels->first; label; label=label->next ) {
+ if( label->position >= dst_pos )
+ label->position += dst_len;
+ }
+ }
+ if( edit_autos ) {
+ for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
+ Autos *autos = track->automation->autos[i];
+ if( !autos ) continue;
+ for( Auto *aut0=autos->first; aut0; aut0=aut0->next ) {
+ if( aut0->position >= start )
+ aut0->position += edit->length;
+ }
+ }
+ }
+ if( edit_plugins ) {
+ for( int i=0; i<track->plugin_set.size(); ++i ) {
+ PluginSet *plugin_set = track->plugin_set[i];
+ Plugin *plugin = (Plugin *)plugin_set->first;
+ for( ; plugin; plugin=(Plugin *)plugin->next ) {
+ if( plugin->startproject >= start )
+ plugin->startproject += edit->length;
+ else if( plugin->startproject+plugin->length > end )
+ plugin->length += edit->length;
+ Auto *default_keyframe = plugin->keyframes->default_auto;
+ if( default_keyframe->position >= start )
+ default_keyframe->position += edit->length;
+ KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first;
+ for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
+ if( keyframe->position >= start )
+ keyframe->position += edit->length;
+ }
+ }
+ plugin_set->optimize();
+ }
+ }
+ }
+ }
+ if( edit_autos ) {
+ for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
+ Autos *src_autos = src->automation->autos[i];
+ if( !src_autos ) continue;
+ Autos *autos = track->automation->autos[i];
+ for( Auto *aut0=src_autos->first; aut0; aut0=aut0->next ) {
+ int64_t auto_pos = pos + aut0->position;
+ autos->insert_auto(auto_pos, aut0);
+ }
+ }
+ }
+ if( edit_plugins ) {
+ for( int i=0; i<src->plugin_set.size(); ++i ) {
+ PluginSet *plugin_set = src->plugin_set[i];
+ if( !plugin_set ) continue;
+ while( i >= track->plugin_set.size() )
+ track->plugin_set.append(0);
+ PluginSet *dst_plugin_set = track->plugin_set[i];
+ if( !dst_plugin_set ) {
+ dst_plugin_set = new PluginSet(this, track);
+ track->plugin_set[i] = dst_plugin_set;
+ }
+ Plugin *plugin = (Plugin *)plugin_set->first;
+ if( plugin ) track->expand_view = 1;
+ for( ; plugin; plugin=(Plugin *)plugin->next ) {
+ int64_t start = pos + plugin->startproject;
+ int64_t end = start + plugin->length;
+ if( overwrite || edit_edits )
+ dst_plugin_set->clear(start, end, 1);
+ Plugin *new_plugin = dst_plugin_set->insert_plugin(plugin->title,
+ start, end-start, plugin->plugin_type, &plugin->shared_location,
+ (KeyFrame*)plugin->keyframes->default_auto, 0);
+ KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first;
+ for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
+ int64_t keyframe_pos = pos + keyframe->position;
+ new_plugin->keyframes->insert_auto(keyframe_pos, keyframe);
+ }
+ while( (new_plugin=(Plugin *)new_plugin->next) ) {
+ KeyFrame *keyframe = (KeyFrame*)new_plugin->keyframes->first;
+ for( ; keyframe; keyframe=(KeyFrame*)keyframe->next )
+ keyframe->position += plugin->length;
+ }
+ }
+ }
+ }
+ src = src->next;
+ }
+ if( edit_labels ) {
+ Label *edl_label = labels->first;
+ for( Label *label=clip->labels->first; label; label=label->next ) {
+ double label_pos = position + label->position;
+ int exists = 0;
+ while( edl_label &&
+ !(exists=equivalent(edl_label->position, label_pos)) &&
+ edl_label->position < position ) edl_label = edl_label->next;
+ if( exists ) continue;
+ labels->insert_before(edl_label,
+ new Label(this, labels, label_pos, label->textstr));
+ }
+ }
+ optimize();
+}
+
+void EDL::paste_edits(EDL *clip, Track *first_track, double position, int overwrite)
+{
+ paste_edits(clip, first_track, position, overwrite, 1,
+ session->labels_follow_edits,
+ session->autos_follow_edits,
+ session->plugins_follow_edits);
+}
+
// return next/prev edit starting from position
double next_edit(double position);
double prev_edit(double position);
+ double skip_silence(double position);
// Debug
int dump(FILE *fp=stdout);
static int next_id();
int insert_clips(ArrayList<EDL*> *new_edls, int load_mode, Track *first_track = 0);
// Add a copy of EDL* to the clip array. Returns the copy.
EDL* add_clip(EDL *edl);
+ EDL *selected_edits_to_clip(int packed,
+ double *start_position, Track **start_track,
+ int edit_labels, int edit_autos, int edit_plugins);
+ EDL *selected_edits_to_clip(int packed, double *start_position, Track **start_track);
+ void selected_edits_to_clipboard(int packed);
+ void paste_edits(EDL *clip, Track *first_track, double position, int overwrite,
+ int edit_edits, int edit_labels, int edit_autos, int edit_plugins);
+ void paste_edits(EDL *clip, Track *first_track, double position, int overwrite);
// resequence group ids starting at next_id
int regroup(int next_id);
const char *prop = properties[i]->prop;
const char *value = properties[i]->value;
int plen = strlen(prop), vlen = strlen(value);
- bool need_quotes = !vlen || strchr(value,' ');
+ bool need_quotes = !vlen || strchr(value,' ') || strchr(value,'\n');
buf->next(' ');
xml->append_text(prop, plen);
buf->next('=');
#include "transportque.h"
#include "zwindow.h"
+// c = corr(a,b): A=fft(a),B=fft(b) C=A*conj(B) c=ifft(C)
+static inline void conj_product(int n, double *rp, double *ip,
+ double *arp, double *aip, double *brp, double *bip)
+{
+ for( int i=0; i<n; ++i ) {
+ double ar = arp[i], ai = aip[i];
+ double br = brp[i], bi = -bip[i];
+ rp[i] = ar*br - ai*bi;
+ ip[i] = ar*bi + ai*br;
+ }
+}
+
MixersAlignMixer::MixersAlignMixer(Mixer *mix)
{
this->mixer = mix;
this->nudge = 0;
mx = 0; mi = -1;
+ br = 0; bi = 0;
aidx = -1;
}
+MixersAlignMixer::~MixersAlignMixer()
+{
+ delete [] br;
+ delete [] bi;
+}
const char *MixersAlignMixerList::mix_titles[MIX_SZ] = {
N_("Mixer"), N_("Nudge"),
cols[MTK_NO].append(new BC_ListBoxItem(no_text));
char mixer_text[BCSTRLEN];
Track *track = mtrk->track;
- int midx = -1, m = dialog->mixer_of(track, midx);
- snprintf(mixer_text, sizeof(mixer_text),"%d:%d", m+1,midx);
+ int k = -1, m = dialog->mixer_of(track, k);
+ snprintf(mixer_text, sizeof(mixer_text),"%d:%d", m+1,k);
cols[MTK_MIXER].append(new BC_ListBoxItem(mixer_text));
cols[MTK_TRACK].append(new BC_ListBoxItem(track->title));
}
this->track = trk;
this->no = no;
this->nudge = 0;
+ this->ss = 0;
mx = 0; mi = -1;
}
+MixersAlignATrack::~MixersAlignATrack()
+{
+}
+
const char *MixersAlignATrackList::atk_titles[ATK_SZ] = {
N_("Track"), N_("Audio"), N_("Nudge"), N_("R"), N_("pos"),
{
char atrack_text[BCSTRLEN];
Track *track = atrack->track;
- int midx = -1, m = dialog->mixer_of(track, midx);
+ int m = dialog->mixer_of(track);
snprintf(atrack_text, sizeof(atrack_text), "%d/%d", atrack->no+1,m+1);
cols[ATK_TRACK].append(new BC_ListBoxItem(atrack_text));
cols[ATK_AUDIO].append(new BC_ListBoxItem(track->title));
int MixersAlignMatch::handle_event()
{
if( !dialog->thread->running() ) {
- gui->reset->disable();
- gui->match->disable();
- gui->apply->disable();
- gui->undo->disable();
- dialog->thread->start();
+ dialog->thread->start(1);
}
return 1;
}
-MixersAlignApply::MixersAlignApply(MixersAlignWindow *gui,
+MixersAlignMatchAll::MixersAlignMatchAll(MixersAlignWindow *gui,
+ MixersAlign *dialog, int x, int y)
+ : BC_GenericButton(x, y, _("Match All"))
+{
+ this->gui = gui;
+ this->dialog = dialog;
+}
+
+int MixersAlignMatchAll::handle_event()
+{
+ if( !dialog->thread->running() ) {
+ dialog->thread->start(0);
+ }
+ return 1;
+}
+
+MixersAlignNudgeTracks::MixersAlignNudgeTracks(MixersAlignWindow *gui,
MixersAlign *dialog, int x, int y)
: BC_GenericButton(x, y, _("Apply"))
{
this->dialog = dialog;
}
-int MixersAlignApply::calculate_width(BC_WindowBase *gui)
+int MixersAlignNudgeTracks::calculate_width(BC_WindowBase *gui)
{
return BC_GenericButton::calculate_w(gui, _("Apply"));
}
-int MixersAlignApply::handle_event()
+int MixersAlignNudgeTracks::handle_event()
+{
+ dialog->nudge_tracks();
+ return 1;
+}
+
+MixersAlignNudgeSelected::MixersAlignNudgeSelected(MixersAlignWindow *gui,
+ MixersAlign *dialog, int x, int y)
+ : BC_GenericButton(x, y, _("Move"))
+{
+ this->gui = gui;
+ this->dialog = dialog;
+}
+
+int MixersAlignNudgeSelected::calculate_width(BC_WindowBase *gui)
+{
+ return BC_GenericButton::calculate_w(gui, _("Move"));
+}
+
+int MixersAlignNudgeSelected::handle_event()
{
- dialog->apply();
+ dialog->nudge_selected();
+ return 1;
+}
+
+MixersAlignUndoItem::MixersAlignUndoItem(const char *text, int no)
+ : BC_MenuItem(text)
+{
+ this->no = no;
+}
+MixersAlignUndoItem::~MixersAlignUndoItem()
+{
+}
+
+int MixersAlignUndoItem::handle_event()
+{
+ MixersAlignUndo *undo = (MixersAlignUndo *)get_popup_menu();
+ undo->dialog->apply_undo(no);
return 1;
}
MixersAlignUndo::MixersAlignUndo(MixersAlignWindow *gui,
MixersAlign *dialog, int x, int y)
- : BC_GenericButton(x, y, _("Undo"))
+ : BC_PopupMenu(x, y, 100, _("Undo"))
{
this->gui = gui;
this->dialog = dialog;
}
+MixersAlignUndo::~MixersAlignUndo()
+{
+}
-int MixersAlignUndo::handle_event()
+void MixersAlignUndo::create_objects()
{
- MWindow *mwindow = dialog->mwindow;
- mwindow->edl->copy_all(dialog->undo_edl);
- mwindow->gui->lock_window("MixersAlignUndo::handle_event");
- mwindow->update_gui(1);
- mwindow->gui->unlock_window();
- return gui->reset->handle_event();
+ add_undo_item(0);
+}
+
+void MixersAlignUndo::add_undo_item(int no)
+{
+ char text[BCSTRLEN];
+ if( no > 0 )
+ sprintf(text, _("chkpt %d"), no);
+ else
+ sprintf(text, _("start over"));
+ add_item(new MixersAlignUndoItem(text, no));
+}
+
+MixersAlignCheckPoint::MixersAlignCheckPoint(MixersAlignWindow *gui,
+ MixersAlign *dialog, int x, int y)
+ : BC_GenericButton(x, y, 100, _("CheckPoint"))
+{
+ this->gui = gui;
+ this->dialog = dialog;
}
+int MixersAlignCheckPoint::handle_event()
+{
+ dialog->check_point();
+ return 1;
+}
MixersAlignWindow::MixersAlignWindow(MixersAlign *dialog, int x, int y)
: BC_Window(_("Align Mixers"), x, y, 880, 380, 880, 380, 1)
atrack_title = new BC_Title(x3,y, _("Audio Tracks:"), MEDIUMFONT, YELLOW);
add_subwindow(atrack_title);
y += mixer_title->get_h() + 10;
- int y1 = y, y2 = get_h() - BC_OKButton::calculate_h() - 15;
+ int y1 = y, y2 = get_h() - BC_OKButton::calculate_h() - 32;
int lh = y2 - y1;
mixer_list = new MixersAlignMixerList(this, dialog, x1, y, x2-x1-20, lh);
add_subwindow(mixer_list);
atrack_list = new MixersAlignATrackList(this, dialog, x3, y, x4-x3-20, lh);
add_subwindow(atrack_list);
int xr = x2-10 - MixersAlignReset::calculate_width(this);
- add_subwindow(reset = new MixersAlignReset(this, dialog, xr, y2+20));
- add_subwindow(match = new MixersAlignMatch(this, dialog, x2+10, y2+20));
- int xa = x3-10 - MixersAlignApply::calculate_width(this);
- add_subwindow(apply = new MixersAlignApply(this, dialog, xa, y2+20));
- add_subwindow(undo = new MixersAlignUndo(this, dialog, x3+10, y2+20));
+ y1 = y2+20;
+ add_subwindow(reset = new MixersAlignReset(this, dialog, xr, y1));
+ add_subwindow(match = new MixersAlignMatch(this, dialog, x2+10, y1));
+ int xa = x3-10 - MixersAlignNudgeTracks::calculate_width(this);
+ add_subwindow(nudge_tracks = new MixersAlignNudgeTracks(this, dialog, xa, y1));
+ y2 = y1 + nudge_tracks->get_h() + 10;
+ add_subwindow(match_all = new MixersAlignMatchAll(this, dialog, xr, y2));
+ add_subwindow(nudge_selected = new MixersAlignNudgeSelected(this, dialog, xa, y2));
+ int xu = x3+10;
+ add_subwindow(check_point = new MixersAlignCheckPoint(this, dialog, xu, y1));
+ add_subwindow(undo = new MixersAlignUndo(this, dialog, xu, y2));
+ undo->create_objects();
add_subwindow(new BC_OKButton(this));
add_subwindow(new BC_CancelButton(this));
mtrack_title->reposition_window(x2, y);
atrack_title->reposition_window(x3, y);
y += mixer_title->get_h() + 10;
- int y1 = y, y2 = h - BC_OKButton::calculate_h() - 15;
+ int y1 = y, y2 = h - BC_OKButton::calculate_h() - 32;
int lh = y2 - y1;
mixer_list->reposition_window(x1, y, x2-x1-20, lh);
mtrack_list->reposition_window(x2, y, x3-x2-20, lh);
atrack_list->reposition_window(x3, y, x4-x3-20, lh);
int xr = x2-10 - MixersAlignReset::calculate_width(this);
- reset->reposition_window(xr, y2+20);
- match->reposition_window(x2+10, y2+20);
- int xa = x3-10 - MixersAlignApply::calculate_width(this);
- apply->reposition_window(xa, y2+20);
- undo->reposition_window(x3+10, y2+20);
+ y1 = y2+20;
+ reset->reposition_window(xr, y1);
+ match->reposition_window(x2+10, y1);
+ int xa = x3-10 - MixersAlignNudgeTracks::calculate_width(this);
+ nudge_tracks->reposition_window(xa, y1);
+ y2 = y1 + nudge_tracks->get_h() + 10;
+ match_all->reposition_window(xr, y2);
+ nudge_selected->reposition_window(xa, y2);
+ int xu = x3+10;
+ check_point->reposition_window(xu, y1);
+ undo->reposition_window(xu, y2);
return 0;
}
master_r = 0;
master_i = 0;
master_len = 0;
+ sample_len = 0x10000;
progress = 0;
failed = 0;
- undo_edl = 0;
master_start = master_end = 0;
audio_start = audio_end = 0;
}
{
this->wx = wx;
this->wy = wy;
- this->undo_edl = new EDL();
- undo_edl->create_objects();
- undo_edl->copy_all(mwindow->edl);
+ EDL *start_over = new EDL();
+ start_over->create_objects();
+ start_over->copy_all(mwindow->edl);
+ undo_edls.append(start_over);
start();
}
return ma_gui;
}
-void MixersAlign::apply()
+// shift armed mixer tracks by nudge
+void MixersAlign::nudge_tracks()
{
int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
- int midx = -1, mid = mixer_of(mtracks[idx]->track, midx);
+ int midx = mmixer_of(idx);
EDL *edl = mwindow->edl;
for( int m, i=0; (m=ma_gui->mixer_list->get_selection_number(0,i))>=0; ++i ) {
- if( m == mid ) continue; // master does not move
+ if( m == midx ) continue; // master does not move
MixersAlignMixer *mix = mixers[m];
Mixer *mixer = mix->mixer;
for( int i=0; i<mixer->mixer_ids.size(); ++i ) {
double nudge = mix->nudge;
int record = track->record; track->record = 1;
if( nudge < 0 ) {
- edl->clear(0, -nudge,
+ track->clear(0, -nudge, 1,
edl->session->labels_follow_edits,
edl->session->plugins_follow_edits,
- edl->session->autos_follow_edits);
+ edl->session->autos_follow_edits, 0);
}
else if( nudge > 0 ) {
- edl->paste_silence(0, nudge,
- edl->session->labels_follow_edits,
+ track->paste_silence(0, nudge,
edl->session->plugins_follow_edits,
edl->session->autos_follow_edits);
}
}
edl->optimize();
- mwindow->gui->lock_window("MixersAlign::handle_done_event");
+ mwindow->gui->lock_window("MixersAlign::apply_tracks");
+ mwindow->update_gui(1);
+ mwindow->gui->unlock_window();
+ clear_mixer_nudge();
+}
+
+// move selected mixer edits by nudge
+void MixersAlign::nudge_selected()
+{
+ int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ int midx = mmixer_of(idx);
+ EDL *edl = mwindow->edl;
+
+ ArrayList<int> track_arms; // ugly
+ for( Track *track=edl->tracks->first; track; track=track->next ) {
+ track_arms.append(track->record);
+ track->record = 0;
+ }
+ for( int m, i=0; (m=ma_gui->mixer_list->get_selection_number(0,i))>=0; ++i ) {
+ if( m == midx ) continue; // master does not move
+ MixersAlignMixer *mix = mixers[m];
+ Mixer *mixer = mix->mixer;
+ for( int i=0; i<mixer->mixer_ids.size(); ++i ) {
+ int id = mixer->mixer_ids[i];
+ Track *track = edl->tracks->first;
+ while( track && track->mixer_id != id ) track = track->next;
+ if( !track ) continue;
+ double nudge = mix->nudge;
+ track->record = 1;
+ double position = 0; Track *first_track = 0;
+ EDL *clip = edl->selected_edits_to_clip(0, &position, &first_track);
+ if( clip ) {
+ Track *clip_track = clip->tracks->first;
+ Track *edl_track = first_track;
+ while( clip_track && edl_track ) {
+ Edit *edit = clip_track->edits->first;
+ for( ; edit; edit=edit->next ) {
+ double start = clip_track->from_units(edit->startproject);
+ double end = clip_track->from_units(edit->startproject+edit->length);
+ start += position; end += position;
+ edl_track->clear(start, end, 1,
+ edl->session->labels_follow_edits,
+ edl->session->plugins_follow_edits,
+ edl->session->autos_follow_edits, 0);
+ edl_track->paste_silence(start, end,
+ edl->session->plugins_follow_edits,
+ edl->session->autos_follow_edits);
+ }
+ clip_track = clip_track->next;
+ edl_track = edl_track->next;
+ }
+ position += nudge;
+ edl->paste_edits(clip, first_track, position, 1);
+ }
+ track->record = 0;
+ }
+ }
+ int i = 0;
+ for( Track *track=edl->tracks->first; track; track=track->next )
+ track->record = track_arms[i++];
+ edl->optimize();
+
+ mwindow->gui->lock_window("MixersAlign::apply_selected");
mwindow->update_gui(1);
mwindow->gui->unlock_window();
+ clear_mixer_nudge();
+}
+
+
+void MixersAlign::clear_mixer_nudge()
+{
+// so pressing apply twice does not damage the result
+ for( int m=0; m<mixers.size(); ++m )
+ mixers[m]->nudge = 0;
+ ma_gui->mixer_list->load_list();
+ ma_gui->lock_window("MixersAlign::clear_mixer_nudge");
+ ma_gui->mixer_list->update();
+ ma_gui->unlock_window();
+}
+
+void MixersAlign::check_point()
+{
+ ma_gui->undo->add_undo_item(undo_edls.size());
+ EDL *undo_edl = new EDL();
+ undo_edl->create_objects();
+ undo_edl->copy_all(mwindow->edl);
+ undo_edls.append(undo_edl);
}
join();
}
+void MixersAlignThread::start(int fwd)
+{
+ this->fwd = fwd;
+ MixersAlignWindow *gui = dialog->ma_gui;
+ gui->reset->disable();
+ gui->match->disable();
+ gui->match_all->disable();
+ gui->nudge_tracks->disable();
+ gui->nudge_selected->disable();
+ gui->check_point->disable();
+// gui->undo->disable();
+ Thread::start();
+}
+
void MixersAlignThread::run()
{
- dialog->update_match();
- MixersAlignWindow *ma_gui = dialog->ma_gui;
- ma_gui->lock_window("MixersAlignThread::run");
- ma_gui->reset->enable();
- ma_gui->match->enable();
- ma_gui->apply->enable();
- ma_gui->undo->enable();
- ma_gui->unlock_window();
+ if( fwd )
+ dialog->match_fwd();
+ else
+ dialog->match_rev();
+ MixersAlignWindow *gui = dialog->ma_gui;
+ gui->lock_window("MixersAlignThread::run");
+ gui->reset->enable();
+ gui->match->enable();
+ gui->match_all->enable();
+ gui->nudge_tracks->enable();
+ gui->nudge_selected->enable();
+ gui->check_point->enable();
+// gui->undo->enable();
+ gui->unlock_window();
}
if( thread->running() ) {
failed = -1;
thread->join();
- return;
}
if( !result ) {
EDL *edl = mwindow->edl;
- mwindow->edl = undo_edl;
+ mwindow->edl = undo_edls[0];
mwindow->undo_before();
mwindow->edl = edl;
mwindow->undo_after(_("align mixers"), LOAD_ALL);
void MixersAlign::handle_close_event(int result)
{
- undo_edl->remove_user();
- undo_edl = 0;
ma_gui = 0;
}
}
+int MixersAlign::atrack_of(MixersAlignMixer *mix, int ch)
+{
+ int k = -1;
+ Mixer *mixer = mix->mixer;
+ for( int i=0,n=mixer->mixer_ids.size(); i<n; ++i ) {
+ int id = mixer->mixer_ids[i]; k = atracks.size();
+ while( --k >= 0 && atracks[k]->track->mixer_id != id );
+ if( k < 0 ) continue;
+ if( --ch < 0 ) break;
+ }
+ return k;
+}
+
int MixersAlign::mixer_of(Track *track, int &midx)
{
int id = track->mixer_id, k = mixers.size(), idx = -1;
return k;
}
+
EDL *MixersAlign::mixer_audio_clip(Mixer *mixer)
{
EDL *edl = new EDL(mwindow->edl);
return edl;
}
-int64_t MixersAlign::mixer_tracks_total()
+int64_t MixersAlign::mixer_tracks_total(int midx)
{
int64_t total_len = 0;
int64_t sample_rate = mwindow->edl->get_sample_rate();
- int m = -1, idx = 0;
- for( ; (m=ma_gui->mixer_list->get_selection_number(0, idx))>=0 ; ++idx ) {
+ int m = -1;
+ for( int i=0; (m=ma_gui->mixer_list->get_selection_number(0, i))>=0 ; ++i ) {
+ if( m == midx ) continue;
Mixer *mixer = mixers[m]->mixer;
double render_end = 0;
Track *track = mwindow->edl->tracks->first;
return total_len;
}
+void MixersAlign::apply_undo(int no)
+{
+ if( thread->running() ) {
+ failed = -1;
+ thread->join();
+ }
+ EDL *undo_edl = undo_edls[no];
+ mwindow->edl->copy_all(undo_edl);
+ mwindow->gui->lock_window("MixersAlignUndo::handle_event");
+ mwindow->update_gui(1);
+ mwindow->gui->unlock_window();
+ ma_gui->reset->handle_event();
+}
+
MixersAlignARender::MixersAlignARender(MWindow *mwindow, EDL *edl)
: RenderEngine(0, mwindow->preferences, 0, 0)
{
return arender ? arender->process_buffer(samples, len, pos) : -1;
}
-MixersAlignPackage::MixersAlignPackage()
+// scan mixer tracks for best target
+MixersAlignScanFarm::MixersAlignScanFarm(MixersAlign *dialog, int cpus, int n)
+ : LoadServer(cpus, n)
+{
+ dialog->farming->lock("MixersAlignScanFarm::MixersAlignScanFarm");
+ this->dialog = dialog;
+ this->len = len;
+}
+MixersAlignScanFarm::~MixersAlignScanFarm()
+{
+ dialog->farming->unlock();
+}
+
+MixersAlignScanPackage::MixersAlignScanPackage(MixersAlignScanFarm *farm)
{
mixer = 0;
}
+MixersAlignScanPackage::~MixersAlignScanPackage()
+{
+}
-MixersAlignPackage::~MixersAlignPackage()
+LoadPackage* MixersAlignScanFarm::new_package()
{
+ return new MixersAlignScanPackage(this);
}
-MixersAlignFarm::MixersAlignFarm(MixersAlign *dialog, int n)
- : LoadServer(bmin(dialog->mwindow->preferences->processors, n), n)
+void MixersAlignScanFarm::init_packages()
{
- this->dialog = dialog;
- dialog->farming->lock("MixersAlignFarm::MixersAlignFarm");
+ int idx = dialog->ma_gui->mtrack_list->get_selection_number(0, 0);
+ int midx = dialog->mmixer_of(idx);
+ for( int i=0, k=0; i<get_total_packages(); ++k ) {
+ int m = dialog->ma_gui->mixer_list->get_selection_number(0, k);
+ if( m == midx ) continue;
+ MixersAlignScanPackage *pkg = (MixersAlignScanPackage *)get_package(i++);
+ pkg->mixer = dialog->mixers[m];
+ }
}
-MixersAlignFarm::~MixersAlignFarm()
+
+MixersAlignScanClient::MixersAlignScanClient(MixersAlignScanFarm *farm)
+ : LoadClient(farm)
{
- dialog->farming->unlock();
+ pos = -1;
+ len1 = 0;
}
-LoadPackage* MixersAlignFarm::new_package()
+MixersAlignScanClient::~MixersAlignScanClient()
{
- return new MixersAlignPackage();
}
-void MixersAlignFarm::init_packages()
+LoadClient* MixersAlignScanFarm::new_client()
{
- for( int i = 0; i < get_total_packages(); ++i ) {
- int m = dialog->ma_gui->mixer_list->get_selection_number(0, i);
- MixersAlignPackage *package = (MixersAlignPackage *)get_package(i);
- package->mixer = dialog->mixers[m];
+ return new MixersAlignScanClient(this);
+}
+
+void MixersAlignScanClient::process_package(LoadPackage *package)
+{
+ MixersAlignScanFarm *farm = (MixersAlignScanFarm *)server;
+ MixersAlign *dialog = farm->dialog;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ if( dialog->failed ) return;
+ pkg = (MixersAlignScanPackage *)package;
+ MixersAlignMixer *mix = pkg->mixer;
+
+ EDL *edl = dialog->mixer_audio_clip(mix->mixer);
+ MixersAlignARender audio(dialog->mwindow, edl);
+ double start = edl->skip_silence(0);
+ int channels = edl->get_audio_channels();
+ int64_t sample_rate = edl->get_sample_rate();
+ int64_t cur_pos = start * sample_rate;
+ int64_t end_pos = edl->get_audio_samples();
+ int len = dialog->sample_len, len2 = len/2;
+ cur_pos &= ~(len2-1);
+ if( cur_pos ) dialog->update_progress(cur_pos);
+
+ int ret = 0;
+ Samples *samples[MAX_CHANNELS];
+ for( int i=0; i<MAX_CHANNELS; ++i )
+ samples[i] = i<channels ? new Samples(len2) : 0;
+ int cpus = bmin(dialog->mwindow->preferences->processors, channels);
+ MixersAlignTarget targ(channels, cpus, this, samples, len2);
+
+ while( !ret && !dialog->failed && cur_pos < end_pos ) {
+ pos = cur_pos;
+ int64_t nxt_pos = pos + len2;
+ if( nxt_pos > end_pos ) nxt_pos = end_pos;
+ len1 = nxt_pos - cur_pos;
+ ret = audio.render(samples, len1, pos);
+ if( ret ) break;
+ targ.process_packages();
+ dialog->update_progress(len1);
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ cur_pos = nxt_pos;
+ }
+
+ if( !ret && !dialog->failed ) {
+ int idx = -1;
+ double sd2 = 0;
+ MixersAlignMixer *mix = pkg->mixer;
+ MixersAlignTargetPackage *best_pkg = 0;
+ for( int i=0,n=targ.get_total_packages(); i<n; ++i ) {
+ MixersAlignTargetPackage *targ_pkg =
+ (MixersAlignTargetPackage *) targ.get_package(i);
+ if( sd2 >= targ_pkg->sd2 ) continue;
+ sd2 = targ_pkg->sd2;
+ int k = dialog->atrack_of(mix, i);
+ if( k < 0 ) continue;
+ MixersAlignATrack *atrk = dialog->atracks[k];
+ atrk->mi = targ_pkg->pos;
+ atrk->ss = targ_pkg->ss;
+ idx = k; best_pkg = targ_pkg;
+ }
+ if( idx >= 0 ) {
+ mix->br = new double[len];
+ mix->bi = new double[len];
+ double *br = mix->br;
+ double *bp = best_pkg->best;
+ int i = 0;
+ while( i < len2 ) br[i++] = *bp++;
+ while( i < len ) br[i++] = 0;
+ FFT fft;
+ fft.do_fft(len, 0, mix->br, 0, mix->br, mix->bi);
+ mix->aidx = idx;
+ }
+ }
+
+ if( ret && !dialog->failed ) {
+ eprintf("Audio render failed:\n%s", edl->path);
+ dialog->failed = 1;
}
+
+ for( int i=channels; --i>=0; ) delete samples[i];
+ edl->remove_user();
+}
+
+// scan mixer channels for best target
+MixersAlignTarget::MixersAlignTarget(int n, int cpus,
+ MixersAlignScanClient *scan, Samples **samples, int len)
+ : LoadServer(n, cpus)
+{
+ this->scan = scan;
+ this->samples = samples;
+ this->len = len;
+}
+MixersAlignTarget::~MixersAlignTarget()
+{
}
-LoadClient* MixersAlignFarm::new_client()
+MixersAlignTargetClient::MixersAlignTargetClient()
+ : LoadClient()
+{
+}
+MixersAlignTargetClient::~MixersAlignTargetClient()
{
- return new MixersAlignClient(this);
}
-MixersAlignClient::MixersAlignClient(MixersAlignFarm *farm)
- : LoadClient(farm)
+LoadClient* MixersAlignTarget::new_client()
{
+ return new MixersAlignTargetClient();
}
-MixersAlignClient::~MixersAlignClient()
+MixersAlignTargetPackage::MixersAlignTargetPackage(MixersAlignTarget *targ)
{
+ ss = 0; sd2 = 0;
+ pos = -1;
+ best = new double[targ->len];
+}
+MixersAlignTargetPackage::~MixersAlignTargetPackage()
+{
+ delete [] best;
}
-void MixersAlignClient::process_package(LoadPackage *pkg)
+LoadPackage* MixersAlignTarget::new_package()
{
- MixersAlignFarm *farm = (MixersAlignFarm *)server;
- MixersAlign *dialog = farm->dialog;
- MixersAlignPackage *package = (MixersAlignPackage *)pkg;
- dialog->process_package(farm, package);
+ return new MixersAlignTargetPackage(this);
}
-static inline void conj_product(int n, double *rp, double *ip,
- double *arp, double *aip, double *brp, double *bip)
+void MixersAlignTarget::init_packages()
{
- for( int i=0; i<n; ++i ) {
- double ar = arp[i], ai = aip[i];
- double br = brp[i], bi = -bip[i];
- rp[i] = ar*br - ai*bi;
- ip[i] = ar*bi + ai*br;
- }
}
-void MixersAlign::process_package(MixersAlignFarm *farm,
- MixersAlignPackage *package)
+void MixersAlignTargetClient::process_package(LoadPackage *package)
{
- if( progress->is_cancelled() ) failed = -1;
- if( failed ) return;
- MixersAlignMixer *amix = package->mixer;
- EDL *edl = mixer_audio_clip(amix->mixer);
+ MixersAlignTarget *targ = (MixersAlignTarget *)server;
+ MixersAlignScanClient *scan = targ->scan;
+ MixersAlignScanFarm *farm = (MixersAlignScanFarm *)scan->server;
+ MixersAlign *dialog = farm->dialog;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ if( dialog->failed ) return;
+ pkg = (MixersAlignTargetPackage *)package;
+
+ int ch = get_package_number();
+ double *data = targ->samples[ch]->get_data();
+ int len1 = scan->len1;
+// computes sum(s**2), sum(d2**2) d2=discrete 2nd deriv
+// d0=s[i+0]-s[i+1], d1=s[i+1]-s[i+2], d2=d0-d1
+// d = s[i+0] - 2*s[i+1] + s[i+2]
+ double ss = 0, sd2 = 0;
+ double a = 0, b = 0, c = 0;
+ for( int i=0; i<len1; ++i ) {
+ a = b; b = c; c = data[i];
+ double d = a - 2*b + c;
+ ss += c*c; sd2 += d*d;
+ }
+//best is highest sd2
+ if( pkg->sd2 < sd2 ) {
+ pkg->sd2 = sd2;
+ pkg->ss = ss;
+ pkg->pos = scan->pos;
+printf("targ %s:%d at %jd,ss=%f sd2=%f\n",
+ scan->pkg->mixer->mixer->title, ch, scan->pos, ss, sd2);
+ double *best = pkg->best;
+ int i = 0, len = targ->len;
+ while( i < len1 ) best[i++] = *data++;
+ while( i < len ) best[i++] = 0;
+ }
+}
+void MixersAlign::scan_master(Track *track)
+{
+ EDL *edl = mixer_master_clip(track);
MixersAlignARender audio(mwindow, edl);
- int sample_rate = edl->get_sample_rate();
+
int channels = edl->get_audio_channels();
+ int64_t sample_rate = edl->get_sample_rate();
int64_t audio_samples = edl->get_audio_samples();
int64_t cur_pos = audio_start * sample_rate;
int64_t end_pos = audio_end * sample_rate;
if( end_pos > audio_samples ) end_pos = audio_samples;
- int len = master_len, len2 = len/2;
+ if( cur_pos >= end_pos ) {
+ eprintf(_("scan master track empty"));
+ failed = 1;
+ return;
+ }
+ int len = sample_len, len2 = len/2;
double *audio_r = new double[len];
double *audio_i = new double[len];
Samples *samples[2][MAX_CHANNELS];
for( int i=0; i<MAX_CHANNELS; ++i )
samples[k][i] = i<channels ? new Samples(len2) : 0;
}
+
+ int m = 0;
+ for( int i=0,n=mixers.size(); i<n; ++i )
+ if( mixers[i]->br ) ++m;
+ int cpus = bmin(mwindow->preferences->processors, m);
+ MixersAlignMatchRevFarm farm(m, cpus, this, audio_r, audio_i, len);
+
+ FFT fft;
+ Timer timer;
+ start_progress(end_pos - cur_pos);
+
int k = 0;
- int64_t nxt_pos = cur_pos+len2;
+ int64_t pos = cur_pos, nxt_pos = cur_pos+len2;
if( nxt_pos > end_pos ) nxt_pos = end_pos;
- int len1 = nxt_pos - cur_pos;
- int ret = audio.render(samples[k], len1, cur_pos);
+ int len1 = nxt_pos - pos;
+ int ret = audio.render(samples[k], len1, pos);
while( !ret && !failed && cur_pos < end_pos ) {
- update_progress(len1);
- int64_t pos = cur_pos;
+ pos = cur_pos;
cur_pos = nxt_pos; nxt_pos += len2;
if( nxt_pos > end_pos ) nxt_pos = end_pos;
len1 = nxt_pos - cur_pos;
ret = audio.render(samples[1-k], len1, cur_pos);
if( ret ) break;
+ update_progress(len2);
+ int i = 0;
+ double *lp = samples[k][0]->get_data();
+ for( int j=0; j<len2; ++j ) audio_r[i++] = *lp++;
+ double *np = samples[k=1-k][0]->get_data();
+ for( int j=0; j<len1; ++j ) audio_r[i++] = *np++;
+ while( i < len ) audio_r[i++] = 0;
+ fft.do_fft(len, 0, audio_r, 0, audio_r, audio_i);
+ farm.pos = pos;
+ farm.process_packages();
+ if( progress->is_cancelled() ) failed = -1;
+ }
+
+ if( ret && !failed ) {
+ eprintf("Audio render failed:\n%s", edl->path);
+ failed = 1;
+ }
+
+ char text[BCSTRLEN];
+ double secs = timer.get_difference()/1000.;
+ sprintf(text, _("Match mixer done: %0.3f secs"), secs);
+ stop_progress(text);
+
+ delete [] audio_r;
+ delete [] audio_i;
+ for( int k=0; k<2; ++k ) {
+ for( int i=channels; --i>=0; )
+ delete samples[k][i];
+ }
+ edl->remove_user();
+}
+
+MixersAlignMatchFwdPackage::MixersAlignMatchFwdPackage()
+{
+ mixer = 0;
+}
+
+MixersAlignMatchFwdPackage::~MixersAlignMatchFwdPackage()
+{
+}
+
+MixersAlignMatchFwdFarm::MixersAlignMatchFwdFarm(MixersAlign *dialog, int n)
+ : LoadServer(bmin(dialog->mwindow->preferences->processors, n), n)
+{
+ this->dialog = dialog;
+ dialog->farming->lock("MixersAlignMatchFwdFarm::MixersAlignMatchFwdFarm");
+}
+MixersAlignMatchFwdFarm::~MixersAlignMatchFwdFarm()
+{
+ dialog->farming->unlock();
+}
+
+LoadPackage* MixersAlignMatchFwdFarm::new_package()
+{
+ return new MixersAlignMatchFwdPackage();
+}
+
+void MixersAlignMatchFwdFarm::init_packages()
+{
+ for( int i = 0; i < get_total_packages(); ++i ) {
+ int m = dialog->ma_gui->mixer_list->get_selection_number(0, i);
+ MixersAlignMatchFwdPackage *package = (MixersAlignMatchFwdPackage *)get_package(i);
+ package->mixer = dialog->mixers[m];
+ }
+}
+
+LoadClient* MixersAlignMatchFwdFarm::new_client()
+{
+ return new MixersAlignMatchFwdClient(this);
+}
+
+MixersAlignMatchFwdClient::MixersAlignMatchFwdClient(MixersAlignMatchFwdFarm *farm)
+ : LoadClient(farm)
+{
+}
+
+MixersAlignMatchFwdClient::~MixersAlignMatchFwdClient()
+{
+}
+
+void MixersAlignMatchFwdClient::process_package(LoadPackage *package)
+{
+ MixersAlignMatchFwdFarm *farm = (MixersAlignMatchFwdFarm *)server;
+ MixersAlign *dialog = farm->dialog;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ if( dialog->failed ) return;
+ pkg = (MixersAlignMatchFwdPackage *)package;
+
+ MixersAlignMixer *amix = pkg->mixer;
+ EDL *edl = dialog->mixer_audio_clip(amix->mixer);
+ MixersAlignARender audio(dialog->mwindow, edl);
+ int channels = edl->get_audio_channels();
+ int64_t sample_rate = edl->get_sample_rate();
+ int64_t audio_samples = edl->get_audio_samples();
+ int64_t cur_pos = dialog->audio_start * sample_rate;
+ int64_t end_pos = dialog->audio_end * sample_rate;
+ if( end_pos > audio_samples ) end_pos = audio_samples;
+ int len = dialog->master_len, len2 = len/2;
+ double *audio_r = new double[len];
+ double *audio_i = new double[len];
+
+ Samples *samples[2][MAX_CHANNELS];
+ for( int k=0; k<2; ++k ) {
+ for( int i=0; i<MAX_CHANNELS; ++i )
+ samples[k][i] = i<channels ? new Samples(len2) : 0;
+ }
+
+ FFT fft;
+ int k = 0;
+ int64_t pos = cur_pos, nxt_pos = cur_pos+len2;
+ if( nxt_pos > end_pos ) nxt_pos = end_pos;
+ int len1 = nxt_pos - pos;
+ int ret = audio.render(samples[k], len1, pos);
+ while( !ret && !dialog->failed && cur_pos < end_pos ) {
+ dialog->update_progress(len1);
+ pos = cur_pos;
+ cur_pos = nxt_pos;
+ nxt_pos += len2;
+ if( nxt_pos > end_pos ) nxt_pos = end_pos;
+ len1 = nxt_pos - cur_pos;
+ ret = audio.render(samples[1-k], len1, cur_pos);
+ if( ret ) break;
Track *track = edl->tracks->first;
for( int ch=0; ch<channels && track; ++ch, track=track->next ) {
- int id = track->mixer_id, atk = atracks.size();
- while( --atk >= 0 && id != atracks[atk]->track->mixer_id );
+ int id = track->mixer_id, atk = dialog->atracks.size();
+ while( --atk >= 0 && id != dialog->atracks[atk]->track->mixer_id );
if( atk < 0 ) continue;
int i = 0;
double *lp = samples[k][ch]->get_data();
double *np = samples[1-k][ch]->get_data();
for( int j=0; j<len1; ++j ) audio_r[i++] = *np++;
while( i < len ) audio_r[i++] = 0;
- do_fft(len, 0, audio_r, 0, audio_r, audio_i);
- conj_product(len, audio_r, audio_i,
- audio_r, audio_i, master_r, master_i);
- do_fft(len, 1, audio_r, audio_i, audio_r, audio_i);
+ fft.do_fft(len, 0, audio_r, 0, audio_r, audio_i);
+ conj_product(len, audio_r, audio_i, audio_r, audio_i,
+ dialog->master_r, dialog->master_i);
+ fft.do_fft(len, 1, audio_r, audio_i);
double mx = 0; int64_t mi = -1;
for( int i=0; i<len2; ++i ) {
double v = fabs(audio_r[i]);
if( mx < v ) { mx = v; mi = i + pos; }
}
- mx /= master_ss;
- MixersAlignATrack *atrack= atracks[atk];
+ mx /= dialog->master_ss;
+ MixersAlignATrack *atrack= dialog->atracks[atk];
if( atrack->mx < mx ) {
atrack->mx = mx;
atrack->mi = mi;
}
}
k = 1-k;
- if( progress->is_cancelled() ) failed = -1;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
}
- if( ret && !failed ) {
+ if( ret && !dialog->failed ) {
eprintf("Audio render failed:\n%s", edl->path);
- failed = 1;
+ dialog->failed = 1;
}
delete [] audio_r;
delete [] audio_i;
}
+MixersAlignMatchRevFarm::MixersAlignMatchRevFarm(int n, int cpus,
+ MixersAlign *dialog, double *ar, double *ai, int len)
+ : LoadServer(n, cpus)
+{
+ this->dialog = dialog;
+ this->ar = ar;
+ this->ai = ai;
+ this->len = len;
+ mixer_lock = new Mutex("MixersAlignMatchRevFarm::mixer_lock");
+ pos = -1;
+}
+MixersAlignMatchRevFarm::~MixersAlignMatchRevFarm()
+{
+ delete mixer_lock;
+}
+
+MixersAlignMatchRevPackage::MixersAlignMatchRevPackage()
+{
+ mix = 0;
+}
+MixersAlignMatchRevPackage::~MixersAlignMatchRevPackage()
+{
+}
+
+void MixersAlignMatchRevFarm::init_packages()
+{
+ for( int i=0,m=0,n=dialog->mixers.size(); m<n; ++m ) {
+ if( !dialog->mixers[m]->br ) continue;
+ MixersAlignMatchRevPackage *pkg = (MixersAlignMatchRevPackage *)get_package(i++);
+ pkg->mix = dialog->mixers[m];
+ }
+}
+
+LoadClient *MixersAlignMatchRevFarm::new_client()
+{
+ return new MixersAlignMatchRevClient(this);
+}
+LoadPackage *MixersAlignMatchRevFarm::new_package()
+{
+ return new MixersAlignMatchRevPackage();
+}
+
+void MixersAlignMatchRevClient::process_package(LoadPackage *package)
+{
+ MixersAlignMatchRevFarm *farm = (MixersAlignMatchRevFarm *)server;
+ MixersAlign *dialog = farm->dialog;
+ if( dialog->progress->is_cancelled() ) dialog->failed = -1;
+ if( dialog->failed ) return;
+ pkg = (MixersAlignMatchRevPackage *)package;
+ MixersAlignMixer *mix = pkg->mix;
+ if( mix->aidx < 0 ) return;
+ int64_t ss = dialog->atracks[mix->aidx]->ss;
+
+ conj_product(farm->len, re, im, farm->ar, farm->ai, mix->br, mix->bi);
+ FFT fft;
+ fft.do_fft(farm->len, 1, re, im);
+ double mx = 0; int64_t mi = -1;
+ for( int i=0,n=farm->len/2; i<n; ++i ) {
+ double r = fabs(re[i]) / ss;
+ if( mx < r ) {
+ mx = r;
+ mi = i + farm->pos;
+ }
+ }
+ farm->mixer_lock->lock("MixersAlignMatchRevFarm::process_package");
+ if( mix->mx < mx ) {
+ mix->mx = mx;
+ mix->mi = mi;
+printf("best %d: %f at %jd\n", get_package_number(), mx, mi);
+ }
+ farm->mixer_lock->unlock();
+}
+
+MixersAlignMatchRevClient::MixersAlignMatchRevClient(MixersAlignMatchRevFarm *farm)
+{
+ re = new double[farm->len];
+ im = new double[farm->len];
+}
+MixersAlignMatchRevClient::~MixersAlignMatchRevClient()
+{
+ delete [] re;
+ delete [] im;
+}
+
+void MixersAlign::start_progress(int64_t total_len)
+{
+ total_rendered = 0;
+ mwindow->gui->lock_window("MixersAlign::start_progress");
+ progress = mwindow->mainprogress->
+ start_progress(_("match mixer audio"), total_len);
+ mwindow->gui->unlock_window();
+}
+void MixersAlign::stop_progress(const char *msg)
+{
+ mwindow->gui->lock_window("MixersAlign::stop_progress");
+ progress->update(0);
+ mwindow->mainprogress->end_progress(progress);
+ progress = 0;
+ if( msg ) mwindow->gui->show_message(msg);
+ mwindow->gui->unlock_window();
+}
+
+void MixersAlign::reset_targets()
+{
+ for( int m=0,n=mixers.size(); m<n; ++m ) {
+ MixersAlignMixer *mix = mixers[m];
+ delete mix->br; mix->br = 0;
+ delete mix->bi; mix->bi = 0;
+ mix->mi = 0;
+ mix->aidx = -1;
+ }
+ for( int i=0,n=atracks.size(); i<n; ++i ) {
+ MixersAlignATrack *atrk = atracks[i];
+ atrk->nudge = 0; atrk->ss = 0;
+ atrk->mx = 0; atrk->mi = -1;
+ }
+}
+
+void MixersAlign::scan_targets()
+{
+ int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ int midx = mmixer_of(idx);
+ int64_t total_len = mixer_tracks_total(midx);
+ start_progress(total_len);
+ int m = mixers.size();
+ if( midx >= 0 ) --m;
+ int cpus = bmin(mwindow->preferences->processors, m);
+ MixersAlignScanFarm scan(this, cpus, m);
+ scan.process_packages();
+ stop_progress(0);
+}
+
void MixersAlign::update_progress(int64_t len)
{
total_lock->lock();
{
EDL *edl = mixer_master_clip(track);
MixersAlignARender audio(mwindow, edl);
- int sample_rate = edl->get_sample_rate();
int channels = edl->get_audio_channels();
+ int64_t sample_rate = edl->get_sample_rate();
int64_t audio_samples = edl->get_audio_samples();
int64_t cur_pos = master_start * sample_rate;
int64_t end_pos = master_end * sample_rate;
delete [] master_r; master_r = new double[master_len];
delete [] master_i; master_i = new double[master_len];
}
- { Samples *samples[MAX_CHANNELS];
- for( int i=0; i<MAX_CHANNELS; ++i )
- samples[i] = i<channels ? new Samples(audio_len) : 0;
- int ret = audio.render(samples, audio_len, cur_pos);
- if( ret ) failed = 1;
- edl->remove_user();
+
+ Samples *samples[MAX_CHANNELS];
+ for( int i=0; i<MAX_CHANNELS; ++i )
+ samples[i] = i<channels ? new Samples(audio_len) : 0;
+ int ret = audio.render(samples, audio_len, cur_pos);
+ if( ret ) failed = 1;
+ edl->remove_user();
+ if( !failed ) {
double *dp = samples[0]->get_data();
int i = 0; double ss = 0;
for( ; i<audio_len; ++i ) { ss += *dp * *dp; master_r[i] = *dp++; }
master_ss = ss;
for( ; i<fft_len; ++i ) master_r[i] = 0;
- for( int i=channels; --i>=0; )
- delete samples[i];
+ for( int i=channels; --i>=0; ) delete samples[i];
}
do_fft(fft_len, 0, master_r, 0, master_r, master_i);
}
}
Timer timer;
- total_rendered = 0;
- MixersAlignFarm farm(this, n);
- int64_t total_len = mixer_tracks_total();
- mwindow->gui->lock_window("MixersAlign::scan_mixer_audio");
- progress = mwindow->mainprogress->
- start_progress(_("Render mixer audio"), total_len);
- mwindow->gui->unlock_window();
+ MixersAlignMatchFwdFarm farm(this, n);
+ int64_t total_len = mixer_tracks_total(-1);
+ start_progress(total_len);
farm.process_packages();
if( progress->is_cancelled() ) failed = -1;
char text[BCSTRLEN];
double secs = timer.get_difference()/1000.;
sprintf(text, _("Render mixer done: %0.3f secs"), secs);
- mwindow->gui->lock_window("MixersAlign::scan_mixer_audio");
- progress->update(0);
- mwindow->mainprogress->end_progress(progress);
- progress = 0;
- mwindow->gui->show_message(text);
- mwindow->gui->unlock_window();
+ stop_progress(text);
}
-void MixersAlign::update_match()
+void MixersAlign::match_fwd()
{
- int midx = ma_gui->mtrack_list->get_selection_number(0, 0);
- if( midx < 0 ) {
+ int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ if( idx < 0 ) {
eprintf(_("selection (master) not set"));
return;
}
}
failed = 0;
- if( !failed ) load_master_audio(mtracks[midx]->track);
- if( !failed ) scan_mixer_audio();
- if( !failed ) update();
+ if( !failed )
+ load_master_audio(mtracks[idx]->track);
+ if( !failed )
+ scan_mixer_audio();
+ if( !failed )
+ update_fwd();
if( failed < 0 ) {
- mwindow->gui->lock_window("MixersAlign::update_match");
+ mwindow->gui->lock_window("MixersAlign::update_match_fwd");
mwindow->gui->show_message(_("mixer selection match canceled"));
mwindow->gui->unlock_window();
}
eprintf(_("Error in match render."));
}
-void MixersAlign::update()
+void MixersAlign::match_rev()
+{
+ int midx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ if( midx < 0 ) {
+ eprintf(_("selection (master) not set"));
+ return;
+ }
+ Track *track = mtracks[midx]->track;
+ audio_start = mwindow->edl->local_session->get_selectionstart();
+ audio_end = mwindow->edl->local_session->get_selectionend();
+ if( audio_start >= audio_end ) {
+ eprintf(_("selection (audio start/end) invalid"));
+ return;
+ }
+
+ reset_targets();
+ failed = 0;
+
+ if( !failed )
+ scan_targets();
+ if( !failed )
+ scan_master(track);
+ if( !failed )
+ update_rev();
+
+ if( failed < 0 ) {
+ mwindow->gui->lock_window("MixersAlign::update_match_rev");
+ mwindow->gui->show_message(_("mixer selection match canceled"));
+ mwindow->gui->unlock_window();
+ }
+ else if( failed > 0 )
+ eprintf(_("Error in match render."));
+}
+
+void MixersAlign::update_fwd()
{
+ double sample_rate = mwindow->edl->get_sample_rate();
+ int64_t mi = master_start * sample_rate;
// mixer best matches
for( int m=0; m<mixers.size(); ++m ) {
MixersAlignMixer *mix = mixers[m];
while( --k >= 0 && atracks[k]->track->mixer_id != id );
if( k < 0 ) continue;
MixersAlignATrack *atrk = atracks[k];
- atrk->nudge = atrk->mi < 0 ? 0 :
- master_start - atrk->track->from_units(atrk->mi);
+ atrk->nudge = atrk->mi < 0 ? -1 :
+ (mi - atrk->mi) / sample_rate;
if( mix->mx >= atrk->mx ) continue;
mix->aidx = k;
mix->mx = atrk->mx;
mix->nudge = atrk->nudge;
}
}
+ update();
+}
+
+void MixersAlign::update_rev()
+{
+ int idx = ma_gui->mtrack_list->get_selection_number(0, 0);
+ int midx = mmixer_of(idx);
+ double sample_rate = mwindow->edl->get_sample_rate();
+ for( int m=0,n=mixers.size(); m<n; ++m ) {
+ if( m == midx ) continue;
+ if( !ma_gui->mixer_list->is_selected(m) ) continue;
+ MixersAlignMixer *mix = mixers[m];
+ if( mix->aidx < 0 ) continue;
+ MixersAlignATrack *atrk = atracks[mix->aidx];
+ mix->nudge = atrk->mi < 0 ? -1 :
+ (mix->mi - atrk->mi) / sample_rate;
+ atrk->mx = mix->mx;
+ }
+ update();
+}
+void MixersAlign::update()
+{
ma_gui->lock_window("MixersAlign::update");
ma_gui->mixer_list->load_list();
ma_gui->mixer_list->set_all_selected(1);
#ifndef __MIXERSALIGN_H__
#define __MIXERSALIGN_H__
-#include "edl.inc"
+#include "edl.h"
+#include "edit.inc"
#include "fourier.h"
#include "guicast.h"
#include "language.h"
{
public:
MixersAlignMixer(Mixer *mix);
+ ~MixersAlignMixer();
Mixer *mixer;
double nudge;
double mx;
int64_t mi;
+ double *br, *bi;
int aidx;
};
{
public:
MixersAlignATrack(Track *trk, int no);
+ ~MixersAlignATrack();
+
Track *track;
int no;
double nudge;
+ double ss;
double mx;
int64_t mi;
};
public:
MixersAlignThread(MixersAlign *dialog);
~MixersAlignThread();
+ void start(int fwd);
void run();
MixersAlign *dialog;
+ int fwd;
};
class MixersAlignMatch : public BC_GenericButton
MixersAlignWindow *gui;
};
-class MixersAlignApply : public BC_GenericButton
+class MixersAlignMatchAll : public BC_GenericButton
{
public:
- MixersAlignApply(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
+ MixersAlignMatchAll(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
+ int handle_event();
+
+ MixersAlign *dialog;
+ MixersAlignWindow *gui;
+};
+
+class MixersAlignNudgeTracks : public BC_GenericButton
+{
+public:
+ MixersAlignNudgeTracks(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
int handle_event();
static int calculate_width(BC_WindowBase *gui);
MixersAlignWindow *gui;
};
-class MixersAlignUndo : public BC_GenericButton
+class MixersAlignNudgeSelected : public BC_GenericButton
{
public:
- MixersAlignUndo(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
+ MixersAlignNudgeSelected(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
+ int handle_event();
+ static int calculate_width(BC_WindowBase *gui);
+
+ MixersAlign *dialog;
+ MixersAlignWindow *gui;
+};
+
+class MixersAlignCheckPoint : public BC_GenericButton
+{
+public:
+ MixersAlignCheckPoint(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
int handle_event();
MixersAlign *dialog;
MixersAlignWindow *gui;
};
+class MixersAlignUndoEDLs : public ArrayList<EDL *>
+{
+public:
+ MixersAlignUndoEDLs() {}
+ ~MixersAlignUndoEDLs() {
+ for( int i=size(); --i>=0; ) get(i)->remove_user();
+ }
+};
+
+class MixersAlignUndoItem : public BC_MenuItem
+{
+public:
+ MixersAlignUndoItem(const char *text, int no);
+ ~MixersAlignUndoItem();
+ int handle_event();
+
+ int no;
+};
+
+class MixersAlignUndo : public BC_PopupMenu
+{
+public:
+ MixersAlignUndo(MixersAlignWindow *gui, MixersAlign *dialog, int x, int y);
+ ~MixersAlignUndo();
+ void create_objects();
+ void add_undo_item(int no);
+
+ MixersAlign *dialog;
+ MixersAlignWindow *gui;
+};
+
class MixersAlignWindow : public BC_Window
{
MixersAlignMTrackList *mtrack_list;
MixersAlignATrackList *atrack_list;
MixersAlignMatch *match;
+ MixersAlignMatchAll *match_all;
MixersAlignReset *reset;
- MixersAlignApply *apply;
+ MixersAlignNudgeTracks *nudge_tracks;
+ MixersAlignNudgeSelected *nudge_selected;
+ MixersAlignCheckPoint *check_point;
MixersAlignUndo *undo;
};
int render(Samples **samples, int64_t len, int64_t pos);
};
-class MixersAlignPackage : public LoadPackage
+
+class MixersAlignScanPackage : public LoadPackage
{
public:
- MixersAlignPackage();
- ~MixersAlignPackage();
+ MixersAlignScanPackage(MixersAlignScanFarm *farm);
+ ~MixersAlignScanPackage();
MixersAlignMixer *mixer;
};
-class MixersAlignClient : public LoadClient
+class MixersAlignScanClient : public LoadClient
+{
+public:
+ MixersAlignScanClient(MixersAlignScanFarm *farm);
+ ~MixersAlignScanClient();
+ void process_package(LoadPackage *package);
+
+ MixersAlignScanFarm *farm;
+ MixersAlignScanPackage *pkg;
+ int64_t pos;
+ int len1;
+};
+
+class MixersAlignScanFarm : public LoadServer
{
public:
- MixersAlignClient(MixersAlignFarm *farm);
- ~MixersAlignClient();
+ MixersAlignScanFarm(MixersAlign *dialog, int cpus, int n);
+ ~MixersAlignScanFarm();
+ void init_packages();
+ LoadClient *new_client();
+ LoadPackage *new_package();
- void process_package(LoadPackage *pkg);
+ MixersAlign *dialog;
+ Samples *samples;
+ int len;
};
-class MixersAlignFarm : public LoadServer
+
+class MixersAlignMatchFwdPackage : public LoadPackage
{
public:
- MixersAlignFarm(MixersAlign *dialog, int n);
- ~MixersAlignFarm();
+ MixersAlignMatchFwdPackage();
+ ~MixersAlignMatchFwdPackage();
+
+ MixersAlignMixer *mixer;
+};
+
+class MixersAlignMatchFwdClient : public LoadClient
+{
+public:
+ MixersAlignMatchFwdClient(MixersAlignMatchFwdFarm *farm);
+ ~MixersAlignMatchFwdClient();
+
+ void process_package(LoadPackage *package);
+ MixersAlignMatchFwdPackage *pkg;
+};
+
+class MixersAlignMatchFwdFarm : public LoadServer
+{
+public:
+ MixersAlignMatchFwdFarm(MixersAlign *dialog, int n);
+ ~MixersAlignMatchFwdFarm();
+ void init_packages();
+ LoadClient *new_client();
+ LoadPackage *new_package();
+
+ MixersAlign *dialog;
+};
+
+
+class MixersAlignMatchRevPackage : public LoadPackage
+{
+public:
+ MixersAlignMatchRevPackage();
+ ~MixersAlignMatchRevPackage();
+
+ MixersAlignMixer *mix;
+};
+
+class MixersAlignMatchRevClient : public LoadClient
+{
+public:
+ MixersAlignMatchRevClient(MixersAlignMatchRevFarm *farm);
+ ~MixersAlignMatchRevClient();
+
+ void process_package(LoadPackage *package);
+ MixersAlignMatchRevPackage *pkg;
+ double *re, *im;
+};
+
+class MixersAlignMatchRevFarm : public LoadServer
+{
+public:
+ MixersAlignMatchRevFarm(int n, int cpus,
+ MixersAlign *dialog, double *ar, double *ai, int len);
+ ~MixersAlignMatchRevFarm();
void init_packages();
LoadClient *new_client();
LoadPackage *new_package();
MixersAlign *dialog;
+ Mutex *mixer_lock;
+ double *ar, *ai;
+ int len;
+ int64_t pos;
};
+
+class MixersAlignTargetPackage : public LoadPackage
+{
+public:
+ MixersAlignTargetPackage(MixersAlignTarget *pfft);
+ ~MixersAlignTargetPackage();
+
+ double ss, sd2;
+ int64_t pos;
+ double *best;
+};
+
+class MixersAlignTargetClient : public LoadClient
+{
+public:
+ MixersAlignTargetClient();
+ ~MixersAlignTargetClient();
+
+ void process_package(LoadPackage *package);
+ MixersAlignTargetPackage *pkg;
+};
+
+class MixersAlignTarget : public LoadServer
+{
+public:
+ MixersAlignTarget(int n, int cpus,
+ MixersAlignScanClient *scan, Samples **samples, int len);
+ ~MixersAlignTarget();
+ void init_packages();
+ LoadClient *new_client();
+ LoadPackage *new_package();
+
+ MixersAlignScanClient *scan;
+ Samples **samples;
+ int len;
+};
+
+
class MixersAlign : public BC_DialogThread, public FFT
{
public:
void handle_done_event(int result);
void handle_close_event(int result);
+ int atrack_of(MixersAlignMixer *mix, int ch);
int mixer_of(Track *track, int &midx);
int mixer_of(Track *track) { int midx = -1; return mixer_of(track, midx); }
int mmixer_of(int mi) {
EDL *mixer_audio_clip(Mixer *mixer);
EDL *mixer_master_clip(Track *track);
- int64_t mixer_tracks_total();
+ int64_t mixer_tracks_total(int midx);
void load_master_audio(Track *track);
void scan_mixer_audio();
+ void start_progress(int64_t total_len);
+ void stop_progress(const char *msg);
void update_progress(int64_t len);
- void update_match();
+ void match_fwd();
+ void match_rev();
+ void update_fwd();
+ void update_rev();
void update();
- void process_package(MixersAlignFarm *farm, MixersAlignPackage *package);
- void apply();
+ void apply_undo(int no);
+ void nudge_tracks();
+ void nudge_selected();
+ void clear_mixer_nudge();
+ void check_point();
+ void reset_targets();
+ void scan_targets();
+ void scan_master(Track *track);
MixersAlignWindow *ma_gui;
int wx, wy;
MixersAlignATracks atracks;
MWindow *mwindow;
- EDL *undo_edl;
+ MixersAlignUndoEDLs undo_edls;
Mutex *farming;
MainProgressBar *progress;
MixersAlignThread *thread;
Mutex *total_lock;
int64_t total_rendered;
int failed;
- int64_t master_len;
+ int64_t master_len, sample_len;
double *master_r, *master_i;
double master_start, master_end, master_ss;
double audio_start, audio_end;
class MixersAlignATrack;
class MixersAlignATracks;
class MixersAlignATrackList;
+class MixersAlignReset;
+class MixersAlignThread;
+class MixersAlignMatch;
+class MixersAlignMatchAll;
+class MixersAlignNudgeTracks;
+class MixersAlignNudgeSelected;
+class MixersAlignCheckPoint;
+class MixersAlignUndoEDLs;
+class MixersAlignUndoItem;
+class MixersAlignUndo;
class MixersAlignWindow;
class MixersAlignARender;
-class MixersAlignPackage;
-class MixersAlignClient;
-class MixersAlignFarm;
+class MixersAlignScanPackage;
+class MixersAlignScanClient;
+class MixersAlignScanFarm;
+class MixersAlignMatchFwdPackage;
+class MixersAlignMatchFwdClient;
+class MixersAlignMatchFwdFarm;
+class MixersAlignMatchRevPackage;
+class MixersAlignMatchRevClient;
+class MixersAlignMatchRevFarm;
+class MixersAlignTargetPackage;
+class MixersAlignTargetClient;
+class MixersAlignTarget;
class MixersAlign;
#endif
}
}
-ZWindow *MWindow::create_mixer(Indexable *indexable)
+ZWindow *MWindow::create_mixer(Indexable *indexable, double position)
{
ArrayList<Indexable*> new_assets;
new_assets.append(indexable);
Track *track = edl->tracks->last;
- load_assets(&new_assets, 0, LOADMODE_NEW_TRACKS, 0, 0, 0, 0, 0, 0);
+ load_assets(&new_assets, position, LOADMODE_NEW_TRACKS, 0, 0, 0, 0, 0, 0);
track = !track ? edl->tracks->first : track->next;
Mixer *mixer = 0;
ZWindow *zwindow = get_mixer(mixer);
return zwindow;
}
-void MWindow::create_mixers()
+void MWindow::create_mixers(double position)
{
if( !session->drag_assets->size() &&
!session->drag_clips->size() ) return;
for( int i=0; i<session->drag_assets->size(); ++i ) {
Indexable *indexable = session->drag_assets->get(i);
if( !indexable->have_video() ) continue;
- ZWindow *zwindow = create_mixer(indexable);
+ ZWindow *zwindow = create_mixer(indexable, position);
new_mixers.append(zwindow);
}
for( int i=0; i<session->drag_clips->size(); ++i ) {
Indexable *indexable = (Indexable*)session->drag_clips->get(i);
if( !indexable->have_video() ) continue;
- ZWindow *zwindow = create_mixer(indexable);
+ ZWindow *zwindow = create_mixer(indexable, position);
new_mixers.append(zwindow);
}
void update_vwindow();
// Fit selected time to horizontal display range
void fit_selection();
- EDL *selected_edits_to_clip(int packed,
- double *start_position, Track **start_track,
- int edit_labels, int edit_autos, int edit_plugins);
- void selected_edits_to_clipboard(int packed);
// Fit selected autos to the vertical display range
void fit_autos(int all);
void change_currentautorange(int autogrouptype, int increment, int changemax);
void handle_mixers(EDL *edl, int command, int wait_tracking,
int use_inout, int toggle_audio, int loop_play, float speed);
- ZWindow *create_mixer(Indexable *indexable);
- void create_mixers();
+ ZWindow *create_mixer(Indexable *indexable, double position);
+ void create_mixers(double position = 0);
void refresh_mixers(int dir=1);
void stop_mixers();
void close_mixers(int destroy=1);
// Move edit to new position
void move_edits(ArrayList<Edit*> *edits, Track *track, double position,
int mode); // mode: 0 - mute and overwrite, 1 - cut and paste
- void paste_edits(EDL *clip, Track *first_track, double position, int overwrite,
- int edit_edits, int edit_labels, int edit_autos, int edit_plugins);
+ void selected_edits_to_clipboard(int packed);
void paste_clipboard(Track *first_track, double position, int overwrite,
int edit_edits, int edit_labels, int edit_autos, int edit_plugins);
void move_group(EDL *group, Track *first_track, double position, int overwrite);
}
-EDL *MWindow::selected_edits_to_clip(int packed,
- double *start_position, Track **start_track,
- int edit_labels, int edit_autos, int edit_plugins)
-{
- double start = DBL_MAX, end = DBL_MIN;
- Track *first_track=0, *last_track = 0;
- for( Track *track=edl->tracks->first; track; track=track->next ) {
- if( !track->record ) continue;
- int empty = 1;
- for( Edit *edit=track->edits->first; edit; edit=edit->next ) {
- if( !edit->is_selected || edit->silence() ) continue;
- double edit_pos = track->from_units(edit->startproject);
- if( start > edit_pos ) start = edit_pos;
- if( end < (edit_pos+=edit->length) ) end = edit_pos;
- empty = 0;
- }
- if( empty ) continue;
- if( !first_track ) first_track = track;
- last_track = track;
- }
- if( start_position ) *start_position = start;
- if( start_track ) *start_track = first_track;
- if( !first_track ) return 0;
- EDL *new_edl = new EDL();
- new_edl->create_objects();
- new_edl->copy_session(edl);
- const char *text = _("new_edl edit");
- new_edl->set_path(text);
- strcpy(new_edl->local_session->clip_title, text);
- strcpy(new_edl->local_session->clip_notes, text);
- new_edl->session->video_tracks = 0;
- new_edl->session->audio_tracks = 0;
- for( Track *track=edl->tracks->first; track; track=track->next ) {
- if( !track->record ) continue;
- if( first_track ) {
- if( first_track != track ) continue;
- first_track = 0;
- }
- Track *new_track = 0;
- if( !packed )
- new_track = new_edl->add_new_track(track->data_type);
- int64_t start_pos = track->to_units(start, 0);
- int64_t end_pos = track->to_units(end, 0);
- int64_t startproject = 0;
- Edit *edit = track->edits->first;
- for( ; edit; edit=edit->next ) {
- if( !edit->is_selected || edit->silence() ) continue;
- if( edit->startproject < start_pos ) continue;
- if( edit->startproject >= end_pos ) break;
- int64_t edit_start_pos = edit->startproject;
- int64_t edit_end_pos = edit->startproject + edit->length;
- if( !new_track )
- new_track = new_edl->add_new_track(track->data_type);
- int64_t edit_pos = edit_start_pos - start_pos;
- if( !packed && edit_pos > startproject ) {
- Edit *silence = new Edit(new_edl, new_track);
- silence->startproject = startproject;
- silence->length = edit_pos - startproject;
- new_track->edits->append(silence);
- startproject = edit_pos;
- }
- int64_t clip_start_pos = startproject;
- Edit *clip_edit = new Edit(new_edl, new_track);
- clip_edit->copy_from(edit);
- clip_edit->startproject = startproject;
- startproject += clip_edit->length;
- new_track->edits->append(clip_edit);
- if( edit_labels ) {
- double edit_start = track->from_units(edit_start_pos);
- double edit_end = track->from_units(edit_end_pos);
- double clip_start = new_track->from_units(clip_start_pos);
- Label *label = edl->labels->first;
- for( ; label; label=label->next ) {
- if( label->position < edit_start ) continue;
- if( label->position >= edit_end ) break;
- double clip_position = label->position - edit_start + clip_start;
- Label *clip_label = new_edl->labels->first;
- while( clip_label && clip_label->position<clip_position )
- clip_label = clip_label->next;
- if( clip_label && clip_label->position == clip_position ) continue;
- Label *new_label = new Label(new_edl,
- new_edl->labels, clip_position, label->textstr);
- new_edl->labels->insert_before(clip_label, new_label);
- }
- }
- if( edit_autos ) {
- Automation *automation = track->automation;
- Automation *new_automation = new_track->automation;
- for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
- Autos *autos = automation->autos[i];
- if( !autos ) continue;
- Autos *new_autos = new_automation->autos[i];
- new_autos->default_auto->copy_from(autos->default_auto);
- Auto *aut0 = autos->first;
- for( ; aut0; aut0=aut0->next ) {
- if( aut0->position < edit_start_pos ) continue;
- if( aut0->position >= edit_end_pos ) break;
- Auto *new_auto = new_autos->new_auto();
- new_auto->copy_from(aut0);
- int64_t clip_position = aut0->position - edit_start_pos + clip_start_pos;
- new_auto->position = clip_position;
- new_autos->append(new_auto);
- }
- }
- }
- if( edit_plugins ) {
- while( new_track->plugin_set.size() < track->plugin_set.size() )
- new_track->plugin_set.append(0);
- for( int i=0; i<track->plugin_set.total; ++i ) {
- PluginSet *plugin_set = track->plugin_set[i];
- if( !plugin_set ) continue;
- PluginSet *new_plugin_set = new_track->plugin_set[i];
- if( !new_plugin_set ) {
- new_plugin_set = new PluginSet(new_edl, new_track);
- new_track->plugin_set[i] = new_plugin_set;
- }
- Plugin *plugin = (Plugin*)plugin_set->first;
- int64_t startplugin = new_plugin_set->length();
- for( ; plugin ; plugin=(Plugin*)plugin->next ) {
- if( plugin->silence() ) continue;
- int64_t plugin_start_pos = plugin->startproject;
- int64_t plugin_end_pos = plugin_start_pos + plugin->length;
- if( plugin_end_pos < start_pos ) continue;
- if( plugin_start_pos > end_pos ) break;
- if( plugin_start_pos < edit_start_pos )
- plugin_start_pos = edit_start_pos;
- if( plugin_end_pos > edit_end_pos )
- plugin_end_pos = edit_end_pos;
- if( plugin_start_pos >= plugin_end_pos ) continue;
- int64_t plugin_pos = plugin_start_pos - start_pos;
- if( !packed && plugin_pos > startplugin ) {
- Plugin *silence = new Plugin(new_edl, new_track, "");
- silence->startproject = startplugin;
- silence->length = plugin_pos - startplugin;
- new_plugin_set->append(silence);
- startplugin = plugin_pos;
- }
- Plugin *new_plugin = new Plugin(new_edl, new_track, plugin->title);
- new_plugin->copy_base(plugin);
- new_plugin->startproject = startplugin;
- new_plugin->length = plugin_end_pos - plugin_start_pos;
- startplugin += new_plugin->length;
- new_plugin_set->append(new_plugin);
- KeyFrames *keyframes = plugin->keyframes;
- KeyFrames *new_keyframes = new_plugin->keyframes;
- new_keyframes->default_auto->copy_from(keyframes->default_auto);
- new_keyframes->default_auto->position = new_plugin->startproject;
- KeyFrame *keyframe = (KeyFrame*)keyframes->first;
- for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
- if( keyframe->position < edit_start_pos ) continue;
- if( keyframe->position >= edit_end_pos ) break;
- KeyFrame *clip_keyframe = new KeyFrame(new_edl, new_keyframes);
- clip_keyframe->copy_from(keyframe);
- int64_t key_position = keyframe->position - start_pos;
- if( packed )
- key_position += new_plugin->startproject - plugin_pos;
- clip_keyframe->position = key_position;
- new_keyframes->append(clip_keyframe);
- }
- }
- }
- }
- }
- if( last_track == track ) break;
- }
- return new_edl;
-}
-
-void MWindow::selected_edits_to_clipboard(int packed)
-{
- EDL *new_edl = selected_edits_to_clip(packed, 0, 0,
- edl->session->labels_follow_edits,
- edl->session->autos_follow_edits,
- edl->session->plugins_follow_edits);
- if( !new_edl ) return;
- FileXML file;
- new_edl->copy(COPY_EDL, &file, "", 1);
- const char *file_string = file.string();
- long file_length = strlen(file_string);
- gui->to_clipboard(file_string, file_length, BC_PRIMARY_SELECTION);
- gui->to_clipboard(file_string, file_length, SECONDARY_SELECTION);
- new_edl->remove_user();
-}
-
void MWindow::delete_edit(Edit *edit, const char *msg, int collapse)
{
ArrayList<Edit*> edits;
gui->update(1, NORMAL_DRAW, 1, 0, 0, 0, 0);
}
-void MWindow::paste_edits(EDL *clip, Track *first_track, double position, int overwrite,
- int edit_edits, int edit_labels, int edit_autos, int edit_plugins)
+void MWindow::selected_edits_to_clipboard(int packed)
{
- if( !first_track )
- first_track = edl->tracks->first;
- Track *src = clip->tracks->first;
- for( Track *track=first_track; track && src; track=track->next ) {
- if( !track->record ) continue;
- int64_t pos = track->to_units(position, 0);
- if( edit_edits ) {
- for( Edit *edit=src->edits->first; edit; edit=edit->next ) {
- if( edit->silence() ) continue;
- int64_t start = pos + edit->startproject;
- int64_t len = edit->length, end = start + len;
- if( overwrite )
- track->edits->clear(start, end);
- Edit *dst = track->edits->insert_new_edit(start);
- dst->copy_from(edit);
- dst->startproject = start;
- dst->is_selected = 1;
- while( (dst=dst->next) != 0 )
- dst->startproject += edit->length;
- if( overwrite ) continue;
- if( edit_labels && track == first_track ) {
- double dst_pos = track->from_units(start);
- double dst_len = track->from_units(len);
- for( Label *label=edl->labels->first; label; label=label->next ) {
- if( label->position >= dst_pos )
- label->position += dst_len;
- }
- }
- if( edit_autos ) {
- for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
- Autos *autos = track->automation->autos[i];
- if( !autos ) continue;
- for( Auto *aut0=autos->first; aut0; aut0=aut0->next ) {
- if( aut0->position >= start )
- aut0->position += edit->length;
- }
- }
- }
- if( edit_plugins ) {
- for( int i=0; i<track->plugin_set.size(); ++i ) {
- PluginSet *plugin_set = track->plugin_set[i];
- Plugin *plugin = (Plugin *)plugin_set->first;
- for( ; plugin; plugin=(Plugin *)plugin->next ) {
- if( plugin->startproject >= start )
- plugin->startproject += edit->length;
- else if( plugin->startproject+plugin->length > end )
- plugin->length += edit->length;
- Auto *default_keyframe = plugin->keyframes->default_auto;
- if( default_keyframe->position >= start )
- default_keyframe->position += edit->length;
- KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first;
- for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
- if( keyframe->position >= start )
- keyframe->position += edit->length;
- }
- }
- plugin_set->optimize();
- }
- }
- }
- }
- if( edit_autos ) {
- for( int i=0; i<AUTOMATION_TOTAL; ++i ) {
- Autos *src_autos = src->automation->autos[i];
- if( !src_autos ) continue;
- Autos *autos = track->automation->autos[i];
- for( Auto *aut0=src_autos->first; aut0; aut0=aut0->next ) {
- int64_t auto_pos = pos + aut0->position;
- autos->insert_auto(auto_pos, aut0);
- }
- }
- }
- if( edit_plugins ) {
- for( int i=0; i<src->plugin_set.size(); ++i ) {
- PluginSet *plugin_set = src->plugin_set[i];
- if( !plugin_set ) continue;
- while( i >= track->plugin_set.size() )
- track->plugin_set.append(0);
- PluginSet *dst_plugin_set = track->plugin_set[i];
- if( !dst_plugin_set ) {
- dst_plugin_set = new PluginSet(edl, track);
- track->plugin_set[i] = dst_plugin_set;
- }
- Plugin *plugin = (Plugin *)plugin_set->first;
- if( plugin ) track->expand_view = 1;
- for( ; plugin; plugin=(Plugin *)plugin->next ) {
- int64_t start = pos + plugin->startproject;
- int64_t end = start + plugin->length;
- if( overwrite || edit_edits )
- dst_plugin_set->clear(start, end, 1);
- Plugin *new_plugin = dst_plugin_set->insert_plugin(plugin->title,
- start, end-start, plugin->plugin_type, &plugin->shared_location,
- (KeyFrame*)plugin->keyframes->default_auto, 0);
- KeyFrame *keyframe = (KeyFrame*)plugin->keyframes->first;
- for( ; keyframe; keyframe=(KeyFrame*)keyframe->next ) {
- int64_t keyframe_pos = pos + keyframe->position;
- new_plugin->keyframes->insert_auto(keyframe_pos, keyframe);
- }
- while( (new_plugin=(Plugin *)new_plugin->next) ) {
- KeyFrame *keyframe = (KeyFrame*)new_plugin->keyframes->first;
- for( ; keyframe; keyframe=(KeyFrame*)keyframe->next )
- keyframe->position += plugin->length;
- }
- }
- }
- }
- src = src->next;
- }
- if( edit_labels ) {
- Label *edl_label = edl->labels->first;
- for( Label *label=clip->labels->first; label; label=label->next ) {
- double label_pos = position + label->position;
- int exists = 0;
- while( edl_label &&
- !(exists=edl->equivalent(edl_label->position, label_pos)) &&
- edl_label->position < position ) edl_label = edl_label->next;
- if( exists ) continue;
- edl->labels->insert_before(edl_label,
- new Label(edl, edl->labels, label_pos, label->textstr));
- }
- }
- edl->optimize();
+ EDL *new_edl = edl->selected_edits_to_clip(packed, 0, 0,
+ edl->session->labels_follow_edits,
+ edl->session->autos_follow_edits,
+ edl->session->plugins_follow_edits);
+ if( !new_edl ) return;
+ FileXML file;
+ new_edl->copy(COPY_EDL, &file, "", 1);
+ const char *file_string = file.string();
+ long file_length = strlen(file_string);
+ gui->to_clipboard(file_string, file_length, BC_PRIMARY_SELECTION);
+ gui->to_clipboard(file_string, file_length, SECONDARY_SELECTION);
+ new_edl->remove_user();
}
void MWindow::paste_clipboard(Track *first_track, double position, int overwrite,
clip->create_objects();
if( !clip->load_xml(&file, LOAD_ALL) ) {
undo_before();
- paste_edits(clip, first_track, position, overwrite,
+ edl->paste_edits(clip, first_track, position, overwrite,
edit_edits, edit_labels, edit_autos, edit_plugins);
save_backup();
undo_after(_("paste clip"), LOAD_ALL);
if( edl->session->labels_follow_edits )
edl->delete_edit_labels(&edits, 0);
edl->delete_edits(&edits, 0);
- paste_edits(group, first_track, position, overwrite, 1,
+ edl->paste_edits(group, first_track, position, overwrite, 1,
edl->session->labels_follow_edits,
edl->session->autos_follow_edits,
edl->session->plugins_follow_edits);
// Get starting point of insertion. Need this to paste labels.
switch( load_mode ) {
case LOADMODE_REPLACE:
- case LOADMODE_NEW_TRACKS:
current_position = 0;
+ case LOADMODE_NEW_TRACKS:
break;
case LOADMODE_CONCATENATE:
int result = 1;
Plugin *current_edit;
+// trim plugins before position 0
+ while( first && first->startproject+first->length < 0 )
+ delete first;
+ if( first && first->startproject < 0 ) {
+ first->length += first->startproject;
+ first->startproject = 0;
+ }
// Delete keyframes out of range
for(current_edit = (Plugin*)first;
int Save::save_before_quit()
{
+ mwindow->gui->lock_window("Save::save_before_quit");
saveas->quit_now = 1;
handle_event();
+ mwindow->gui->unlock_window();
return 0;
}
add_subwindow(new BC_Title(mwindow->theme->setformat_x1, y,
_("Channel positions:")));
y += mwindow->theme->setformat_margin;
- add_subwindow(new SetChannelsReset(thread,
+ add_subwindow(channels_reset = new SetChannelsReset(thread,
mwindow->theme->setformat_x1, y,
_("Reset")));
add_subwindow(canvas = new SetChannelsCanvas(mwindow,
int SetFormatPresets::handle_event()
{
format_gui->thread->update();
- return 1;
+ return format_gui->channels_reset->handle_event();
}
EDL* SetFormatPresets::get_edl()
MWindow *mwindow;
SetFormatThread *thread;
+ SetChannelsReset *channels_reset;
SetChannelsCanvas *canvas;
// Screen size width, height
ScaleSizeText* dimension[2];
mwindow->session->drag_group->remove_user();
double start_position = 0;
mwindow->session->drag_group =
- mwindow->selected_edits_to_clip(0, &start_position,
- &mwindow->session->drag_group_first_track,
- mwindow->edl->session->labels_follow_edits,
- mwindow->edl->session->autos_follow_edits,
- mwindow->edl->session->plugins_follow_edits);
+ mwindow->edl->selected_edits_to_clip(0, &start_position,
+ &mwindow->session->drag_group_first_track);
if( mwindow->session->drag_group ) {
mwindow->session->current_operation = DRAG_GROUP;
mwindow->session->drag_group_position = start_position;
}
TransitionUnitsPopup::TransitionUnitsPopup(TransitionLengthDialog *gui, int x, int y)
- : BC_PopupMenu(x, y, 100, "", 1)
+ : BC_PopupMenu(x, y, 120, "", 1)
{
this->gui = gui;
units = TIME_SECONDS;