Example #1
0
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.settings = QtCore.QSettings("bidoul.net", "edledit")

        # initialize media components
        self.mediaObject = self.ui.player.mediaObject()
        self.mediaObject.setTickInterval(200)
        self.mediaObject.stateChanged.connect(self.stateChanged)
        self.mediaObject.tick.connect(self.tick)
        self.ui.edlWidget.seek.connect(self.ui.player.seek)

        # add steps combo box and position widget to toolbar
        # (this apparently can't be done in the designer)
        self.ui.stepCombobox = QtGui.QComboBox(self.ui.toolBar)
        self.ui.stepLabel = QtGui.QLabel(tr(" Step : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime = QtGui.QTimeEdit(self.ui.toolBar)
        self.ui.timeEditCurrentTime.setReadOnly(True)
        self.ui.timeEditCurrentTime.setButtonSymbols(
            QtGui.QAbstractSpinBox.NoButtons)
        self.ui.posLabel = QtGui.QLabel(tr(" Position : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime.setDisplayFormat("HH:mm:ss.zzz")
        self.ui.toolBar.addWidget(self.ui.stepLabel)
        self.ui.toolBar.addWidget(self.ui.stepCombobox)
        self.ui.toolBar.addSeparator()
        self.ui.toolBar.addWidget(self.ui.posLabel)
        self.ui.toolBar.addWidget(self.ui.timeEditCurrentTime)

        # populate steps combo box
        for stepMs, stepText in self.steps:
            self.ui.stepCombobox.addItem(stepText)

        # initialize attributes
        self.loading = False
        self.movieFileName = None
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.setStep(self.defaultStepIndex)
Example #2
0
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.settings = QtCore.QSettings("bidoul.net", "edledit")

        # initialize media components
        self.mediaObject = self.ui.player.mediaObject()
        self.mediaObject.setTickInterval(200)
        self.mediaObject.stateChanged.connect(self.stateChanged)
        self.mediaObject.tick.connect(self.tick)
        self.ui.edlWidget.seek.connect(self.ui.player.seek)

        # add steps combo box and position widget to toolbar
        # (this apparently can't be done in the designer)
        self.ui.stepCombobox = QtGui.QComboBox(self.ui.toolBar)
        self.ui.stepLabel = QtGui.QLabel(tr(" Step : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime = QtGui.QTimeEdit(self.ui.toolBar)
        self.ui.timeEditCurrentTime.setReadOnly(True)
        self.ui.timeEditCurrentTime.setButtonSymbols(
            QtGui.QAbstractSpinBox.NoButtons)
        self.ui.posLabel = QtGui.QLabel(tr(" Position : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime.setDisplayFormat("HH:mm:ss.zzz")
        self.ui.toolBar.addWidget(self.ui.stepLabel)
        self.ui.toolBar.addWidget(self.ui.stepCombobox)
        self.ui.toolBar.addSeparator()
        self.ui.toolBar.addWidget(self.ui.posLabel)
        self.ui.toolBar.addWidget(self.ui.timeEditCurrentTime)

        # populate steps combo box
        for stepMs, stepText in self.steps:
            self.ui.stepCombobox.addItem(stepText)

        # initialize attributes
        self.loading = False
        self.movieFileName = None
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.setStep(self.defaultStepIndex)
Example #3
0
class MainWindow(QtGui.QMainWindow):

    steps = [
        (40, tr("4 msec")),
        (200, tr("20 msec")),
        (500, tr("0.5 sec")),
        (2000, tr("2 sec")),
        (5000, tr("5 sec")),
        (20000, tr("20 sec")),
        (60000, tr("1 min")),
        (300000, tr("5 min")),
        (600000, tr("10 min")),
    ]

    defaultStepIndex = 7

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.settings = QtCore.QSettings("bidoul.net", "edledit")

        # initialize media components
        self.mediaObject = self.ui.player.mediaObject()
        self.mediaObject.setTickInterval(200)
        self.mediaObject.stateChanged.connect(self.stateChanged)
        self.mediaObject.tick.connect(self.tick)
        self.ui.edlWidget.seek.connect(self.ui.player.seek)

        # add steps combo box and position widget to toolbar
        # (this apparently can't be done in the designer)
        self.ui.stepCombobox = QtGui.QComboBox(self.ui.toolBar)
        self.ui.stepLabel = QtGui.QLabel(tr(" Step : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime = QtGui.QTimeEdit(self.ui.toolBar)
        self.ui.timeEditCurrentTime.setReadOnly(True)
        self.ui.timeEditCurrentTime.setButtonSymbols(
            QtGui.QAbstractSpinBox.NoButtons)
        self.ui.posLabel = QtGui.QLabel(tr(" Position : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime.setDisplayFormat("HH:mm:ss.zzz")
        self.ui.toolBar.addWidget(self.ui.stepLabel)
        self.ui.toolBar.addWidget(self.ui.stepCombobox)
        self.ui.toolBar.addSeparator()
        self.ui.toolBar.addWidget(self.ui.posLabel)
        self.ui.toolBar.addWidget(self.ui.timeEditCurrentTime)

        # populate steps combo box
        for stepMs, stepText in self.steps:
            self.ui.stepCombobox.addItem(stepText)

        # initialize attributes
        self.loading = False
        self.movieFileName = None
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.setStep(self.defaultStepIndex)

    # logic

    def loadEDL(self):
        assert self.movieFileName
        self.edlFileName = os.path.splitext(self.movieFileName)[0] + ".edl"
        if os.path.exists(self.edlFileName):
            self.edl = pyedl.load(open(self.edlFileName))
        else:
            self.edl = pyedl.EDL()
        self.edlDirty = False
        self.ui.edlWidget.setEDL(self.edl, self.ui.player.totalTime())
        self.ui.actionSaveEDL.setEnabled(True)
        self.ui.actionStartCut.setEnabled(True)
        self.ui.actionStopCut.setEnabled(True)
        self.ui.actionDeleteCut.setEnabled(True)
        self.refreshTitle()

    def saveEDL(self):
        assert self.edlFileName
        assert self.edl is not None
        self.edl.normalize(timedelta(milliseconds=self.ui.player.totalTime()))
        pyedl.dump(self.edl, open(self.edlFileName, "w"))
        self.edlChanged(dirty=False)

    def closeEDL(self):
        self.ui.actionPreviousCutBoundary.setEnabled(False)
        self.ui.actionNextCutBoundary.setEnabled(False)
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.ui.edlWidget.resetEDL()
        self.ui.actionSaveEDL.setEnabled(False)
        self.ui.actionStartCut.setEnabled(False)
        self.ui.actionStopCut.setEnabled(False)
        self.ui.actionDeleteCut.setEnabled(False)
        self.refreshTitle()

    def play(self):
        if not self.ui.player.isPlaying():
            self.ui.player.play()
            self.ui.actionPlayPause.setChecked(True)

    def pause(self):
        if self.ui.player.isPlaying():
            self.ui.player.pause()
            self.ui.actionPlayPause.setChecked(False)
            self.tick()

    def getStep(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        return self.steps[stepIndex][0]

    def setStep(self, stepIndex):
        stepIndex = max(stepIndex, 0)
        stepIndex = min(stepIndex, len(self.steps)-1)
        self.ui.stepCombobox.setCurrentIndex(stepIndex)
        self.ui.actionDecreaseStep.setEnabled(stepIndex != 0)
        self.ui.actionIncreaseStep.setEnabled(stepIndex != len(self.steps)-1)

    def stepDown(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        self.setStep(stepIndex - 1)

    def stepUp(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        self.setStep(stepIndex + 1)

    def loadMovie(self, fileName):
        self.closeEDL()
        self.loading = True
        self.movieFileName = fileName
        self.ui.player.load(Phonon.MediaSource(self.movieFileName))

    def seekTo(self, pos):
        pos = max(pos, 0)
        pos = min(pos, self.ui.player.totalTime())
        self.ui.player.seek(pos)
        if not self.ui.player.isPlaying():
            self.tick()

    def seekStep(self, step):
        pos = self.ui.player.currentTime() + step
        self.seekTo(pos)

    def edlChanged(self, dirty):
        self.edlDirty = dirty
        self.ui.edlWidget.setEDL(self.edl, self.ui.player.totalTime())
        self.refreshTitle()

    def refreshTitle(self):
        if self.edlFileName:
            if self.edlDirty:
                star = "*"
            else:
                star = ""
            head, tail = os.path.split(os.path.abspath(self.edlFileName))
            self.setWindowTitle("%s%s (%s) - edledit" % (star, tail, head))
        else:
            self.setWindowTitle("edledit")

    # slots

    def closeEvent(self, event):
        if self.askSave():
            event.accept()
        else:
            event.ignore()

    def askSave(self):
        """ If needed, ask the user to save the current EDL

        return True is we can proceed, False is the user selected Cancel.
        """
        if not self.edlDirty:
            return True
        msgBox = QtGui.QMessageBox(self)
        msgBox.setIcon(QtGui.QMessageBox.Question)
        msgBox.setText(tr("The current EDL has been modified."))
        msgBox.setInformativeText(tr("Do you want to save your changes?"))
        msgBox.setStandardButtons(
            QtGui.QMessageBox.Save |
            QtGui.QMessageBox.Discard | QtGui.QMessageBox.Cancel)
        msgBox.setDefaultButton(QtGui.QMessageBox.Save)
        ret = msgBox.exec_()
        if ret == QtGui.QMessageBox.Save:
            self.saveEDL()
            return True
        elif ret == QtGui.QMessageBox.Discard:
            return True
        else:
            return False

    def stateChanged(self, newState, oldState):
        seekable = self.mediaObject.hasVideo() and self.mediaObject.isSeekable()
        self.ui.actionPlayPause.setEnabled(seekable)
        self.ui.actionNextCutBoundary.setEnabled(seekable)
        self.ui.actionPreviousCutBoundary.setEnabled(seekable)
        self.ui.actionSkipBackwards.setEnabled(seekable)
        self.ui.actionSkipForward.setEnabled(seekable)
        if newState == Phonon.StoppedState:
            if self.loading and oldState != Phonon.ErrorState:
                self.play()
        elif newState == Phonon.PlayingState:
            if self.loading:
                self.loading = False
                self.loadEDL()  # TODO quid if error while loading EDL
        elif newState == Phonon.ErrorState:
            if self.loading:
                QtGui.QMessageBox.critical(
                    self,
                    tr("Error loading movie file"),
                    self.mediaObject.errorString())
                self.loading = False
                self.mediaObject.stop()

    def tick(self, timeMs=None):
        if timeMs is None:
            if self.mediaObject.hasVideo():
                timeMs = self.ui.player.currentTime()
            else:
                timeMs = 0
        self.ui.timeEditCurrentTime.setTime(QtCore.QTime(0, 0).addMSecs(timeMs))
        self.ui.edlWidget.tick(timeMs)
        if self.edl:
            block = self.edl.findBlock(ms2timedelta(timeMs))
        else:
            block = None
        if block:
            self.ui.actionDeleteCut.setEnabled(True)
            self.ui.actionCutSetActionSkip.setEnabled(
                block.action != pyedl.ACTION_SKIP)
            self.ui.actionCutSetActionMute.setEnabled(
                block.action != pyedl.ACTION_MUTE)
        else:
            self.ui.actionDeleteCut.setEnabled(False)
            self.ui.actionCutSetActionSkip.setEnabled(False)
            self.ui.actionCutSetActionMute.setEnabled(False)

    def smartSeekBackwards(self):
        self.stepDown()
        if self.getStep() <= 5000:
            self.pause()
        self.seekStep(-self.getStep())

    def smartSeekForward(self):
        self.stepDown()
        if self.getStep() <= 5000:
            self.pause()
        self.seekStep(self.getStep())

    def seekForward(self):
        self.seekStep(self.getStep())

    def seekBackwards(self):
        self.seekStep(-self.getStep())

    def seekNextBoundary(self):
        # self.pause()
        t = ms2timedelta(self.ui.player.currentTime())
        t = self.edl.getNextBoundary(t)
        if t:
            self.seekTo(timedelta2ms(t))
        else:
            self.seekTo(self.ui.player.totalTime())

    def seekPrevBoundary(self):
        # self.pause()
        t = ms2timedelta(self.ui.player.currentTime())
        t = self.edl.getPrevBoundary(t)
        if t:
            self.seekTo(timedelta2ms(t))
        else:
            self.seekTo(0)

    def togglePlayPause(self):
        if not self.ui.player.isPlaying():
            self.play()
        else:
            self.pause()

    def cutStart(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.cutStart(t)
        self.edlChanged(dirty=True)

    def cutStop(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.cutStop(t)
        self.edlChanged(dirty=True)

    def cutDelete(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.deleteBlock(t)
        self.edlChanged(dirty=True)

    def cutSetAction(self, action):
        block = self.edl.findBlock(ms2timedelta(self.ui.player.currentTime()))
        if block is not None:
            block.action = action
            self.edlChanged(dirty=True)

    def cutSetActionSkip(self):
        self.cutSetAction(pyedl.ACTION_SKIP)

    def cutSetActionMute(self):
        self.cutSetAction(pyedl.ACTION_MUTE)

    def actionFileOpen(self):
        if not self.askSave():
            return
        # get video file extensions from mime types database
        exts = ["*" + ext for (ext, mt) in mimetypes.types_map.items()
                if mt.startswith("video/")]
        exts = " ".join(exts)
        lastFolder = self.settings.value("last-folder").toString()
        fileName = QtGui.QFileDialog.getOpenFileName(
            self, tr("Select movie file to open"), lastFolder,
            tr("All Movie Files (%s);;All Files (*.*)") % exts)
        if fileName:
            # unicode() to convert from QString
            fileName = unicode(fileName)
            # save directory so next getOpenFileName will be in same dir
            self.settings.setValue("last-folder", os.path.split(fileName)[0])
            self.loadMovie(fileName)

    def actionFileSaveEDL(self):
        self.saveEDL()

    def actionHelpAbout(self):
        AboutDialog(self).exec_()
Example #4
0
class MainWindow(QtGui.QMainWindow):

    steps = [
        (40, tr("4 msec")),
        (200, tr("20 msec")),
        (500, tr("0.5 sec")),
        (2000, tr("2 sec")),
        (5000, tr("5 sec")),
        (20000, tr("20 sec")),
        (60000, tr("1 min")),
        (300000, tr("5 min")),
        (600000, tr("10 min")),
    ]

    defaultStepIndex = 7

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        self.settings = QtCore.QSettings("bidoul.net", "edledit")

        # initialize media components
        self.mediaObject = self.ui.player.mediaObject()
        self.mediaObject.setTickInterval(200)
        self.mediaObject.stateChanged.connect(self.stateChanged)
        self.mediaObject.tick.connect(self.tick)
        self.ui.edlWidget.seek.connect(self.ui.player.seek)

        # add steps combo box and position widget to toolbar
        # (this apparently can't be done in the designer)
        self.ui.stepCombobox = QtGui.QComboBox(self.ui.toolBar)
        self.ui.stepLabel = QtGui.QLabel(tr(" Step : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime = QtGui.QTimeEdit(self.ui.toolBar)
        self.ui.timeEditCurrentTime.setReadOnly(True)
        self.ui.timeEditCurrentTime.setButtonSymbols(
            QtGui.QAbstractSpinBox.NoButtons)
        self.ui.posLabel = QtGui.QLabel(tr(" Position : "), self.ui.toolBar)
        self.ui.timeEditCurrentTime.setDisplayFormat("HH:mm:ss.zzz")
        self.ui.toolBar.addWidget(self.ui.stepLabel)
        self.ui.toolBar.addWidget(self.ui.stepCombobox)
        self.ui.toolBar.addSeparator()
        self.ui.toolBar.addWidget(self.ui.posLabel)
        self.ui.toolBar.addWidget(self.ui.timeEditCurrentTime)

        # populate steps combo box
        for stepMs, stepText in self.steps:
            self.ui.stepCombobox.addItem(stepText)

        # initialize attributes
        self.loading = False
        self.movieFileName = None
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.setStep(self.defaultStepIndex)

    # logic

    def loadEDL(self):
        assert self.movieFileName
        self.edlFileName = os.path.splitext(self.movieFileName)[0] + ".edl"
        if os.path.exists(self.edlFileName):
            self.edl = pyedl.load(open(self.edlFileName))
        else:
            self.edl = pyedl.EDL()
        self.edlDirty = False
        self.ui.edlWidget.setEDL(self.edl, self.ui.player.totalTime())
        self.ui.actionSaveEDL.setEnabled(True)
        self.ui.actionStartCut.setEnabled(True)
        self.ui.actionStopCut.setEnabled(True)
        self.ui.actionDeleteCut.setEnabled(True)
        self.refreshTitle()

    def saveEDL(self):
        assert self.edlFileName
        assert self.edl is not None
        self.edl.normalize(timedelta(milliseconds=self.ui.player.totalTime()))
        pyedl.dump(self.edl, open(self.edlFileName, "w"))
        self.edlChanged(dirty=False)

    def closeEDL(self):
        self.ui.actionPreviousCutBoundary.setEnabled(False)
        self.ui.actionNextCutBoundary.setEnabled(False)
        self.edlFileName = None
        self.edl = None
        self.edlDirty = False
        self.ui.edlWidget.resetEDL()
        self.ui.actionSaveEDL.setEnabled(False)
        self.ui.actionStartCut.setEnabled(False)
        self.ui.actionStopCut.setEnabled(False)
        self.ui.actionDeleteCut.setEnabled(False)
        self.refreshTitle()

    def play(self):
        if not self.ui.player.isPlaying():
            self.ui.player.play()
            self.ui.actionPlayPause.setChecked(True)

    def pause(self):
        if self.ui.player.isPlaying():
            self.ui.player.pause()
            self.ui.actionPlayPause.setChecked(False)
            self.tick()

    def getStep(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        return self.steps[stepIndex][0]

    def setStep(self, stepIndex):
        stepIndex = max(stepIndex, 0)
        stepIndex = min(stepIndex, len(self.steps) - 1)
        self.ui.stepCombobox.setCurrentIndex(stepIndex)
        self.ui.actionDecreaseStep.setEnabled(stepIndex != 0)
        self.ui.actionIncreaseStep.setEnabled(stepIndex != len(self.steps) - 1)

    def stepDown(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        self.setStep(stepIndex - 1)

    def stepUp(self):
        stepIndex = self.ui.stepCombobox.currentIndex()
        self.setStep(stepIndex + 1)

    def loadMovie(self, fileName):
        self.closeEDL()
        self.loading = True
        self.movieFileName = fileName
        self.ui.player.load(Phonon.MediaSource(self.movieFileName))

    def seekTo(self, pos):
        pos = max(pos, 0)
        pos = min(pos, self.ui.player.totalTime())
        self.ui.player.seek(pos)
        if not self.ui.player.isPlaying():
            self.tick()

    def seekStep(self, step):
        pos = self.ui.player.currentTime() + step
        self.seekTo(pos)

    def edlChanged(self, dirty):
        self.edlDirty = dirty
        self.ui.edlWidget.setEDL(self.edl, self.ui.player.totalTime())
        self.refreshTitle()

    def refreshTitle(self):
        if self.edlFileName:
            if self.edlDirty:
                star = "*"
            else:
                star = ""
            head, tail = os.path.split(os.path.abspath(self.edlFileName))
            self.setWindowTitle("%s%s (%s) - edledit" % (star, tail, head))
        else:
            self.setWindowTitle("edledit")

    # slots

    def closeEvent(self, event):
        if self.askSave():
            event.accept()
        else:
            event.ignore()

    def askSave(self):
        """ If needed, ask the user to save the current EDL

        return True is we can proceed, False is the user selected Cancel.
        """
        if not self.edlDirty:
            return True
        msgBox = QtGui.QMessageBox(self)
        msgBox.setIcon(QtGui.QMessageBox.Question)
        msgBox.setText(tr("The current EDL has been modified."))
        msgBox.setInformativeText(tr("Do you want to save your changes?"))
        msgBox.setStandardButtons(QtGui.QMessageBox.Save
                                  | QtGui.QMessageBox.Discard
                                  | QtGui.QMessageBox.Cancel)
        msgBox.setDefaultButton(QtGui.QMessageBox.Save)
        ret = msgBox.exec_()
        if ret == QtGui.QMessageBox.Save:
            self.saveEDL()
            return True
        elif ret == QtGui.QMessageBox.Discard:
            return True
        else:
            return False

    def stateChanged(self, newState, oldState):
        seekable = self.mediaObject.hasVideo() and self.mediaObject.isSeekable(
        )
        self.ui.actionPlayPause.setEnabled(seekable)
        self.ui.actionNextCutBoundary.setEnabled(seekable)
        self.ui.actionPreviousCutBoundary.setEnabled(seekable)
        self.ui.actionSkipBackwards.setEnabled(seekable)
        self.ui.actionSkipForward.setEnabled(seekable)
        if newState == Phonon.StoppedState:
            if self.loading and oldState != Phonon.ErrorState:
                self.play()
        elif newState == Phonon.PlayingState:
            if self.loading:
                self.loading = False
                self.loadEDL()  # TODO quid if error while loading EDL
        elif newState == Phonon.ErrorState:
            if self.loading:
                QtGui.QMessageBox.critical(self,
                                           tr("Error loading movie file"),
                                           self.mediaObject.errorString())
                self.loading = False
                self.mediaObject.stop()

    def tick(self, timeMs=None):
        if timeMs is None:
            if self.mediaObject.hasVideo():
                timeMs = self.ui.player.currentTime()
            else:
                timeMs = 0
        self.ui.timeEditCurrentTime.setTime(
            QtCore.QTime(0, 0).addMSecs(timeMs))
        self.ui.edlWidget.tick(timeMs)
        if self.edl:
            block = self.edl.findBlock(ms2timedelta(timeMs))
        else:
            block = None
        if block:
            self.ui.actionDeleteCut.setEnabled(True)
            self.ui.actionCutSetActionSkip.setEnabled(
                block.action != pyedl.ACTION_SKIP)
            self.ui.actionCutSetActionMute.setEnabled(
                block.action != pyedl.ACTION_MUTE)
        else:
            self.ui.actionDeleteCut.setEnabled(False)
            self.ui.actionCutSetActionSkip.setEnabled(False)
            self.ui.actionCutSetActionMute.setEnabled(False)

    def smartSeekBackwards(self):
        self.stepDown()
        if self.getStep() <= 5000:
            self.pause()
        self.seekStep(-self.getStep())

    def smartSeekForward(self):
        self.stepDown()
        if self.getStep() <= 5000:
            self.pause()
        self.seekStep(self.getStep())

    def seekForward(self):
        self.seekStep(self.getStep())

    def seekBackwards(self):
        self.seekStep(-self.getStep())

    def seekNextBoundary(self):
        # self.pause()
        t = ms2timedelta(self.ui.player.currentTime())
        t = self.edl.getNextBoundary(t)
        if t:
            self.seekTo(timedelta2ms(t))
        else:
            self.seekTo(self.ui.player.totalTime())

    def seekPrevBoundary(self):
        # self.pause()
        t = ms2timedelta(self.ui.player.currentTime())
        t = self.edl.getPrevBoundary(t)
        if t:
            self.seekTo(timedelta2ms(t))
        else:
            self.seekTo(0)

    def togglePlayPause(self):
        if not self.ui.player.isPlaying():
            self.play()
        else:
            self.pause()

    def cutStart(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.cutStart(t)
        self.edlChanged(dirty=True)

    def cutStop(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.cutStop(t)
        self.edlChanged(dirty=True)

    def cutDelete(self):
        t = timedelta(milliseconds=self.ui.player.currentTime())
        self.edl.deleteBlock(t)
        self.edlChanged(dirty=True)

    def cutSetAction(self, action):
        block = self.edl.findBlock(ms2timedelta(self.ui.player.currentTime()))
        if block is not None:
            block.action = action
            self.edlChanged(dirty=True)

    def cutSetActionSkip(self):
        self.cutSetAction(pyedl.ACTION_SKIP)

    def cutSetActionMute(self):
        self.cutSetAction(pyedl.ACTION_MUTE)

    def actionFileOpen(self):
        if not self.askSave():
            return
        # get video file extensions from mime types database
        exts = [
            "*" + ext for (ext, mt) in mimetypes.types_map.items()
            if mt.startswith("video/")
        ]
        exts = " ".join(exts)
        lastFolder = self.settings.value("last-folder").toString()
        fileName = QtGui.QFileDialog.getOpenFileName(
            self, tr("Select movie file to open"), lastFolder,
            tr("All Movie Files (%s);;All Files (*.*)") % exts)
        if fileName:
            # unicode() to convert from QString
            fileName = unicode(fileName)
            # save directory so next getOpenFileName will be in same dir
            self.settings.setValue("last-folder", os.path.split(fileName)[0])
            self.loadMovie(fileName)

    def actionFileSaveEDL(self):
        self.saveEDL()

    def actionHelpAbout(self):
        AboutDialog(self).exec_()