]> git.sesse.net Git - kdenlive/blobdiff - src/mainwindow.cpp
Initial support for Jog Shuttle devices
[kdenlive] / src / mainwindow.cpp
index 107e284c61b4f280d643320c88ae064941050994..899ce8840b214972ca98c7a00a16474bcc742264 100644 (file)
@@ -42,6 +42,8 @@
 #include <kstandarddirs.h>
 #include <KUrlRequesterDialog>
 #include <KTemporaryFile>
+#include <KActionMenu>
+#include <KMenu>
 #include <ktogglefullscreenaction.h>
 
 #include <mlt++/Mlt.h>
@@ -64,7 +66,7 @@
 
 MainWindow::MainWindow(QWidget *parent)
         : KXmlGuiWindow(parent),
-        m_activeDocument(NULL), m_activeTimeline(NULL), m_renderWidget(NULL) {
+        m_activeDocument(NULL), m_activeTimeline(NULL), m_renderWidget(NULL), m_jogProcess(NULL) {
     parseProfiles();
 
     m_commandStack = new QUndoGroup;
@@ -80,7 +82,6 @@ MainWindow::MainWindow(QWidget *parent)
     m_timelineArea->setCornerWidget(closeTabButton);
     connect(m_timelineArea, SIGNAL(currentChanged(int)), this, SLOT(activateDocument()));
 
-
     initEffects::parseEffectFiles(&m_audioEffects, &m_videoEffects);
     m_monitorManager = new MonitorManager();
 
@@ -106,7 +107,7 @@ MainWindow::MainWindow(QWidget *parent)
 
     transitionConfigDock = new QDockWidget(i18n("Transition"), this);
     transitionConfigDock->setObjectName("transition");
-    transitionConfig = new KListWidget(this);
+    transitionConfig = new TransitionSettings(this);
     transitionConfigDock->setWidget(transitionConfig);
     addDockWidget(Qt::TopDockWidgetArea, transitionConfigDock);
 
@@ -124,6 +125,14 @@ MainWindow::MainWindow(QWidget *parent)
     projectMonitorDock->setWidget(m_projectMonitor);
     addDockWidget(Qt::TopDockWidgetArea, projectMonitorDock);
 
+    recMonitorDock = new QDockWidget(i18n("Record Monitor"), this);
+    recMonitorDock->setObjectName("record_monitor");
+    m_recMonitor = new RecMonitor("record", this);
+    recMonitorDock->setWidget(m_recMonitor);
+    addDockWidget(Qt::TopDockWidgetArea, recMonitorDock);
+
+    connect(m_recMonitor, SIGNAL(addProjectClip(KUrl)), this, SLOT(slotAddProjectClip(KUrl)));
+
     undoViewDock = new QDockWidget(i18n("Undo History"), this);
     undoViewDock->setObjectName("undo_history");
     m_undoView = new QUndoView(this);
@@ -184,6 +193,44 @@ MainWindow::MainWindow(QWidget *parent)
 
     setupGUI(Default, "kdenliveui.rc");
 
+    // build effects menus
+    QAction *action;
+    QMenu *videoEffectsMenu = (QMenu*)(factory()->container("video_effects_menu", this));
+    QStringList effects = m_videoEffects.effectNames();
+    foreach(QString name, effects) {
+        action = new QAction(name, this);
+        action->setData(name);
+        videoEffectsMenu->addAction(action);
+    }
+    QMenu *audioEffectsMenu = (QMenu*)(factory()->container("audio_effects_menu", this));
+    effects = m_audioEffects.effectNames();
+    foreach(QString name, effects) {
+        action = new QAction(name, this);
+        action->setData(name);
+        audioEffectsMenu->addAction(action);
+    }
+    QMenu *customEffectsMenu = (QMenu*)(factory()->container("custom_effects_menu", this));
+    effects = m_customEffects.effectNames();
+    foreach(QString name, effects) {
+        action = new QAction(name, this);
+        action->setData(name);
+        customEffectsMenu->addAction(action);
+    }
+
+    connect(videoEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddVideoEffect(QAction *)));
+    connect(audioEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddAudioEffect(QAction *)));
+    connect(customEffectsMenu, SIGNAL(triggered(QAction *)), this, SLOT(slotAddCustomEffect(QAction *)));
+
+    m_timelineContextMenu = new QMenu(this);
+    m_timelineContextClipMenu = new QMenu(this);
+    m_timelineContextTransitionMenu = new QMenu(this);
+
+    action = actionCollection()->action("delete_timeline_clip");
+    m_timelineContextClipMenu->addAction(action);
+    m_timelineContextClipMenu->addMenu(videoEffectsMenu);
+    m_timelineContextClipMenu->addMenu(audioEffectsMenu);
+    m_timelineContextClipMenu->addMenu(customEffectsMenu);
+
     connect(projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
     connect(clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
     //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors()));
@@ -194,6 +241,8 @@ MainWindow::MainWindow(QWidget *parent)
 
     setAutoSaveSettings();
     newFile();
+
+    activateShuttleDevice();
 }
 
 //virtual
@@ -210,8 +259,54 @@ bool MainWindow::queryClose() {
     }
 }
 
+void MainWindow::activateShuttleDevice() {
+    if (m_jogProcess) delete m_jogProcess;
+    m_jogProcess = NULL;
+    if (KdenliveSettings::enableshuttle() == false) return;
+    m_jogProcess = new JogShuttle(KdenliveSettings::shuttledevice());
+    connect(m_jogProcess, SIGNAL(rewind1()), m_monitorManager, SLOT(slotRewindOneFrame()));
+    connect(m_jogProcess, SIGNAL(forward1()), m_monitorManager, SLOT(slotForwardOneFrame()));
+    connect(m_jogProcess, SIGNAL(rewind(double)), m_monitorManager, SLOT(slotRewind(double)));
+    connect(m_jogProcess, SIGNAL(forward(double)), m_monitorManager, SLOT(slotForward(double)));
+    connect(m_jogProcess, SIGNAL(stop()), m_monitorManager, SLOT(slotPlay()));
+    connect(m_jogProcess, SIGNAL(button(int)), this, SLOT(slotShuttleButton(int)));
+}
+
+void MainWindow::slotShuttleButton(int code) {
+    switch (code) {
+    case 5:
+        slotShuttleAction(KdenliveSettings::shuttle1());
+        break;
+    case 6:
+        slotShuttleAction(KdenliveSettings::shuttle2());
+        break;
+    case 7:
+        slotShuttleAction(KdenliveSettings::shuttle3());
+        break;
+    case 8:
+        slotShuttleAction(KdenliveSettings::shuttle4());
+        break;
+    case 9:
+        slotShuttleAction(KdenliveSettings::shuttle5());
+        break;
+    }
+}
+
+void MainWindow::slotShuttleAction(int code) {
+    switch (code) {
+    case 0:
+       return;
+    case 1:
+        m_monitorManager->slotPlay();
+        break;
+    default:
+        m_monitorManager->slotPlay();
+        break;
+    }
+}
+
 void MainWindow::slotFullScreen() {
-    KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked());
+    //KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked());
 }
 
 void MainWindow::slotAddEffect(QDomElement effect, GenTime pos, int track) {
@@ -278,6 +373,41 @@ void MainWindow::setupActions() {
     actionCollection()->addAction("monitor_play", monitorPlay);
     connect(monitorPlay, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPlay()));
 
+    KAction* monitorSeekBackward = new KAction(this);
+    monitorSeekBackward->setText(i18n("Rewind"));
+    monitorSeekBackward->setIcon(KIcon("media-seek-backward"));
+    monitorSeekBackward->setShortcut(Qt::Key_J);
+    actionCollection()->addAction("monitor_seek_backward", monitorSeekBackward);
+    connect(monitorSeekBackward, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotRewind()));
+
+    KAction* monitorSeekBackwardOneFrame = new KAction(this);
+    monitorSeekBackwardOneFrame->setText(i18n("Rewind 1 Frame"));
+    monitorSeekBackwardOneFrame->setIcon(KIcon("media-skip-backward"));
+    monitorSeekBackwardOneFrame->setShortcut(Qt::Key_Left);
+    actionCollection()->addAction("monitor_seek_backward-one-frame", monitorSeekBackwardOneFrame);
+    connect(monitorSeekBackwardOneFrame, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotRewindOneFrame()));
+
+    KAction* monitorSeekForward = new KAction(this);
+    monitorSeekForward->setText(i18n("Forward"));
+    monitorSeekForward->setIcon(KIcon("media-seek-forward"));
+    monitorSeekForward->setShortcut(Qt::Key_L);
+    actionCollection()->addAction("monitor_seek_forward", monitorSeekForward);
+    connect(monitorSeekForward, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotForward()));
+
+    KAction* monitorSeekForwardOneFrame = new KAction(this);
+    monitorSeekForwardOneFrame->setText(i18n("Forward 1 Frame"));
+    monitorSeekForwardOneFrame->setIcon(KIcon("media-skip-forward"));
+    monitorSeekForwardOneFrame->setShortcut(Qt::Key_Right);
+    actionCollection()->addAction("monitor_seek_forward-one-frame", monitorSeekForwardOneFrame);
+    connect(monitorSeekForwardOneFrame, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotForwardOneFrame()));
+
+    KAction* deleteTimelineClip = new KAction(this);
+    deleteTimelineClip->setText(i18n("Delete Clip"));
+    deleteTimelineClip->setShortcut(Qt::Key_Delete);
+    deleteTimelineClip->setIcon(KIcon("edit-delete"));
+    actionCollection()->addAction("delete_timeline_clip", deleteTimelineClip);
+    connect(deleteTimelineClip, SIGNAL(triggered(bool)), this, SLOT(slotDeleteTimelineClip()));
+
     KStandardAction::quit(kapp, SLOT(quit()),
                           actionCollection());
 
@@ -350,7 +480,7 @@ void MainWindow::newFile() {
     MltVideoProfile prof = ProfilesDialog::getVideoProfile(profileName);
     if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
     KdenliveDoc *doc = new KdenliveDoc(KUrl(), prof, m_commandStack);
-    TrackView *trackView = new TrackView(doc);
+    TrackView *trackView = new TrackView(doc, this);
     m_timelineArea->addTab(trackView, KIcon("kdenlive"), i18n("Untitled") + " / " + prof.description);
     if (m_timelineArea->count() == 1)
         connectDocument(trackView, doc);
@@ -415,7 +545,7 @@ void MainWindow::openFile(const KUrl &url) { //new
     MltVideoProfile prof = ProfilesDialog::getVideoProfile(KdenliveSettings::default_profile());
     if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
     KdenliveDoc *doc = new KdenliveDoc(url, prof, m_commandStack);
-    TrackView *trackView = new TrackView(doc);
+    TrackView *trackView = new TrackView(doc, this);
     m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description()));
     m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), doc->url().path());
     if (m_timelineArea->count() > 1) m_timelineArea->setTabBarHidden(false);
@@ -570,6 +700,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
             disconnect(m_activeDocument, SIGNAL(deletTimelineClip(int)), m_activeTimeline, SLOT(slotDeleteClip(int)));
             disconnect(m_activeDocument, SIGNAL(thumbsProgress(KUrl, int)), this, SLOT(slotGotProgressInfo(KUrl, int)));
             disconnect(m_activeTimeline, SIGNAL(clipItemSelected(ClipItem*)), effectStack, SLOT(slotClipItemSelected(ClipItem*)));
+            disconnect(m_activeTimeline, SIGNAL(transitionItemSelected(Transition*)), transitionConfig, SLOT(slotTransitionItemSelected(Transition*)));
             disconnect(timeline_buttons_ui.zoom_slider, SIGNAL(valueChanged(int)), m_activeTimeline, SLOT(slotChangeZoom(int)));
             disconnect(m_activeDocument, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
             disconnect(effectStack, SIGNAL(updateClipEffect(ClipItem*, QDomElement, QDomElement)), m_activeTimeline->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, QDomElement, QDomElement)));
@@ -597,6 +728,7 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
     connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
 
     connect(trackView, SIGNAL(clipItemSelected(ClipItem*)), effectStack, SLOT(slotClipItemSelected(ClipItem*)));
+    connect(trackView, SIGNAL(transitionItemSelected(Transition*)), transitionConfig, SLOT(slotTransitionItemSelected(Transition*)));
     timeline_buttons_ui.zoom_slider->setValue(trackView->currentZoom());
     connect(timeline_buttons_ui.zoom_slider, SIGNAL(valueChanged(int)), trackView, SLOT(slotChangeZoom(int)));
     connect(trackView->projectView(), SIGNAL(zoomIn()), this, SLOT(slotZoomIn()));
@@ -606,14 +738,15 @@ void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //cha
     connect(effectStack, SIGNAL(changeEffectState(ClipItem*, QDomElement, bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*, QDomElement, bool)));
     connect(effectStack, SIGNAL(refreshEffectStack(ClipItem*)), trackView->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
     connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));
-
-
+    trackView->projectView()->setContextMenu(m_timelineContextMenu, m_timelineContextClipMenu, m_timelineContextTransitionMenu);
     m_activeTimeline = trackView;
     KdenliveSettings::setCurrent_profile(doc->profilePath());
     if (m_renderWidget) m_renderWidget->setDocumentStandard(doc->getDocumentStandard());
     m_monitorManager->setTimecode(doc->timecode());
     doc->setRenderer(m_projectMonitor->render);
     m_commandStack->setActiveStack(doc->commandStack());
+    if (m_commandStack->isClean()) kDebug() << "////////////  UNDO STACK IS CLEAN";
+    else  kDebug() << "////////////  UNDO STACK IS NOT CLEAN*******************";
 
     m_overView->setScene(trackView->projectScene());
     //m_overView->scale(m_overView->width() / trackView->duration(), m_overView->height() / (50 * trackView->tracksNumber()));
@@ -647,6 +780,7 @@ void MainWindow::updateConfiguration() {
     }
     timeline_buttons_ui.buttonAudio->setDown(KdenliveSettings::audiothumbnails());
     timeline_buttons_ui.buttonVideo->setDown(KdenliveSettings::videothumbnails());
+    activateShuttleDevice();
 }
 
 void MainWindow::slotSwitchVideoThumbs() {
@@ -669,6 +803,36 @@ void MainWindow::slotSwitchAudioThumbs() {
     timeline_buttons_ui.buttonAudio->setDown(KdenliveSettings::audiothumbnails());
 }
 
+void MainWindow::slotDeleteTimelineClip() {
+    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
+    if (currentTab) {
+        currentTab->projectView()->deleteSelectedClips();
+    }
+}
+
+void MainWindow::slotAddProjectClip(KUrl url) {
+    if (m_activeDocument)
+        m_activeDocument->slotAddClipFile(url, QString());
+}
+
+void MainWindow::slotAddVideoEffect(QAction *result) {
+    if (!result) return;
+    QDomElement effect = m_videoEffects.getEffectByName(result->data().toString());
+    slotAddEffect(effect);
+}
+
+void MainWindow::slotAddAudioEffect(QAction *result) {
+    if (!result) return;
+    QDomElement effect = m_audioEffects.getEffectByName(result->data().toString());
+    slotAddEffect(effect);
+}
+
+void MainWindow::slotAddCustomEffect(QAction *result) {
+    if (!result) return;
+    QDomElement effect = m_customEffects.getEffectByName(result->data().toString());
+    slotAddEffect(effect);
+}
+
 void MainWindow::slotZoomIn() {
     timeline_buttons_ui.zoom_slider->setValue(timeline_buttons_ui.zoom_slider->value() - 1);
 }
@@ -695,4 +859,12 @@ void MainWindow::slotGotProgressInfo(KUrl url, int progress) {
     }
 }
 
+void MainWindow::customEvent(QEvent* e) {
+    if (e->type() == QEvent::User) {
+        // The timeline playing position changed...
+        kDebug() << "RECIEVED JOG EVEMNT!!!";
+    }
+}
+
+
 #include "mainwindow.moc"