#! /usr/bin/env python3 # -*- coding: utf-8 -*- """ Copyright 2022, Nils Hilbricht, Germany ( https://www.hilbricht.net ) This file is part of the Laborejo Software Suite ( https://www.laborejo.org ), This application is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . """ import logging; logger = logging.getLogger(__name__); logger.info("import") #Standard Library from datetime import timedelta #Third Party from PyQt5 import QtCore, QtGui, QtWidgets #Engine import engine.api as api class JackTransportControls(object): """Singleton object for code-structure reasons""" def __init__(self, mainWindow): self.mainWindow = mainWindow self.ui = self.mainWindow.ui self.visible = None self.currentMaximumInSeconds = self.ui.jackTransportMaxTime.value() * 60 #widget is in minutes self.resolutionFactor = 10 #Around 10 seems to be the maximum. The progressbar will still "Jump" above that. self.ui.jackTransportPlayPause.setCheckable(True) self.ui.jackTransportPlayPause.setText("") self.ui.jackTransportPlayPause.setIcon(QtGui.QIcon(':playpause.png')) self.ui.jackTransportRewind.setText("") self.ui.jackTransportRewind.setIcon(QtGui.QIcon(':tostart.png')) api.callbacks.sessionOpenReady.append(self.show) api.callbacks.sessionClosed.append(self.hide) api.callbacks.setPlaybackSeconds.append(self._react_playbackSeconds) api.callbacks.dataClientTimelineMaximumDurationChanged.append(self._callback_MaximumChanged) self.ui.jackTransportMaxTime.valueChanged.connect(self._gui_MaximumChanged) self.ui.jackTransportPlayPause.clicked.connect(api.jackClient.playPause) self.ui.jackTransportRewind.clicked.connect(api.jackClient.rewind) #Maximum Resolution of 100 is not enough. It is too "steppy" self.ui.jackTransportTimeline.setMaximum(100 * self.resolutionFactor) self.ui.jackTransportTimeline.reset() self.ui.jackTransportTimeline.mousePressEvent = self._timelineMousePressEvent self.ui.jackTransportTimeline.mouseMoveEvent = self._timelineMouseMoveEvent self.hide() def hide(self, *args): self.ui.jackTransportControls.hide() self.visible = False def show(self, *args): self.ui.jackTransportControls.show() self.visible = True def _gui_MaximumChanged(self, minutes:int): """Send to the api. Our own widget will get changed via callback.""" api.setTimelineMaximumDuration(minutes) def _callback_MaximumChanged(self, minutes:int): """Get a new value from the api. This is either from loading or a roundtrip from our own widget change. Can be None if nsm-data left the session. In this case we just ignore and continue.""" if minutes: #0 is not possible. May be None. self.currentMaximumInSeconds = minutes * 60 self.ui.jackTransportMaxTime.blockSignals(True) self.ui.jackTransportMaxTime.setValue(minutes) self.ui.jackTransportMaxTime.blockSignals(False) def _react_playbackSeconds(self, seconds, isTransportRunning): if self.visible: #optimisation realPercent = seconds / self.currentMaximumInSeconds progressPercent = realPercent * 100 * self.resolutionFactor #100 because that is 0.xy -> xy% ) progressPercent = int(progressPercent) prettyTime = str(timedelta(seconds=int(seconds))) #timedelta without int will print microseconds if self.currentMaximumInSeconds < 3600: #less than an hour prettyTime = prettyTime[2:] if progressPercent <= 100 * self.resolutionFactor: self.ui.jackTransportTimeline.setValue(progressPercent) else: self.ui.jackTransportTimeline.setValue(100 * self.resolutionFactor) if isTransportRunning: self.ui.jackTransportPlayPause.setChecked(True) self.ui.jackTransportTimeline.setFormat("▶ " + prettyTime) #we don't use the Qt format substitutions. We just set a fixed value. else: self.ui.jackTransportPlayPause.setChecked(False) self.ui.jackTransportTimeline.setFormat("■ " + prettyTime) def _timelineMousePressEvent(self, event): """The positions are in pixels. If the window is different we get different numbers. Normalize first.""" percentage = event.x() / self.ui.jackTransportTimeline.width() #x is relative to the widget. same as localPos().x() seconds = percentage * self.currentMaximumInSeconds api.jackClient.seek(seconds) def _timelineMouseMoveEvent(self, event): """We did not set any qt-flags on this widget so mouseMoveEvent only works when the left mouse button is down, and not just simply by hovering. Which is exactly what we want: dragging""" percentage = event.x() / self.ui.jackTransportTimeline.width() #x is relative to the widget. same as localPos().x() seconds = percentage * self.currentMaximumInSeconds api.jackClient.seek(seconds)