Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

225 lines
8.2KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Carla host code
  4. # Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU General Public License as
  8. # published by the Free Software Foundation; either version 2 of
  9. # the License, or any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # For a full copy of the GNU General Public License see the doc/GPL.txt file.
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Config)
  19. from carla_config import *
  20. # ------------------------------------------------------------------------------------------------------------
  21. # Imports (Global)
  22. if config_UseQt5:
  23. from PyQt5.QtCore import pyqtSlot
  24. from PyQt5.QtGui import QDialog, QFontMetrics
  25. from PyQt5.QtWidgets import QDialog
  26. else:
  27. from PyQt4.QtCore import pyqtSlot
  28. from PyQt4.QtGui import QDialog, QFontMetrics
  29. # ------------------------------------------------------------------------------------------------------------
  30. # Imports (Custom)
  31. from carla_shared import *
  32. import ui_carla_panel_time
  33. # ------------------------------------------------------------------------------------------------------------
  34. # Time Panel
  35. class CarlaPanelTime(QDialog):
  36. def __init__(self, host, parent):
  37. QDialog.__init__(self, parent)
  38. self.host = host
  39. self.ui = ui_carla_panel_time.Ui_Dialog()
  40. self.ui.setupUi(self)
  41. if False:
  42. # kdevelop likes this :)
  43. host = CarlaHostNull()
  44. self.host = host
  45. # ----------------------------------------------------------------------------------------------------
  46. # Internal stuff
  47. self.fLastTransportBPM = 0.0
  48. self.fLastTransportFrame = 0
  49. self.fLastTransportState = False
  50. self.fSampleRate = 0.0
  51. self.ui.l_time_frame.setMinimumWidth(QFontMetrics(self.ui.l_time_frame.font()).width("000'000'000") + 3)
  52. self.ui.l_time_clock.setMinimumWidth(QFontMetrics(self.ui.l_time_clock.font()).width("00:00:00") + 3)
  53. self.ui.l_time_bbt.setMinimumWidth(QFontMetrics(self.ui.l_time_bbt.font()).width("000|00|0000") + 3)
  54. # ----------------------------------------------------------------------------------------------------
  55. # Disable buttons if plugin
  56. if host.isPlugin:
  57. self.ui.b_play.setEnabled(False)
  58. self.ui.b_stop.setEnabled(False)
  59. self.ui.b_backwards.setEnabled(False)
  60. self.ui.b_forwards.setEnabled(False)
  61. self.ui.cb_transport_link.setEnabled(False)
  62. self.ui.dsb_bpm.setEnabled(False)
  63. # ----------------------------------------------------------------------------------------------------
  64. # Connect actions to functions
  65. self.ui.b_play.clicked.connect(self.slot_transportPlayPause)
  66. self.ui.b_stop.clicked.connect(self.slot_transportStop)
  67. self.ui.b_backwards.clicked.connect(self.slot_transportBackwards)
  68. self.ui.b_forwards.clicked.connect(self.slot_transportForwards)
  69. self.ui.cb_transport_jack.clicked.connect(self.slot_transportJackEnabled)
  70. self.ui.cb_transport_link.clicked.connect(self.slot_transportLinkEnabled)
  71. host.EngineStartedCallback.connect(self.slot_handleEngineStartedCallback)
  72. host.EngineStoppedCallback.connect(self.slot_handleEngineStoppedCallback)
  73. host.SampleRateChangedCallback.connect(self.slot_handleSampleRateChangedCallback)
  74. # --------------------------------------------------------------------------------------------------------
  75. # Button actions
  76. @pyqtSlot(bool)
  77. def slot_transportPlayPause(self, toggled):
  78. if self.host.isPlugin or not self.host.is_engine_running():
  79. return
  80. if toggled:
  81. self.host.transport_play()
  82. else:
  83. self.host.transport_pause()
  84. self.refreshTransport()
  85. @pyqtSlot()
  86. def slot_transportStop(self):
  87. if self.host.isPlugin or not self.host.is_engine_running():
  88. return
  89. self.host.transport_pause()
  90. self.host.transport_relocate(0)
  91. self.refreshTransport()
  92. @pyqtSlot()
  93. def slot_transportBackwards(self):
  94. if self.host.isPlugin or not self.host.is_engine_running():
  95. return
  96. newFrame = self.host.get_current_transport_frame() - 100000
  97. if newFrame < 0:
  98. newFrame = 0
  99. self.host.transport_relocate(newFrame)
  100. @pyqtSlot()
  101. def slot_transportForwards(self):
  102. if self.fSampleRate == 0.0 or self.host.isPlugin or not self.host.is_engine_running():
  103. return
  104. newFrame = self.host.get_current_transport_frame() + int(self.fSampleRate*2.5)
  105. self.host.transport_relocate(newFrame)
  106. @pyqtSlot(bool)
  107. def slot_transportJackEnabled(self, clicked):
  108. if not self.host.is_engine_running():
  109. return
  110. mode = ENGINE_TRANSPORT_MODE_JACK if clicked else ENGINE_TRANSPORT_MODE_INTERNAL
  111. self.host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, mode, "")
  112. @pyqtSlot(bool)
  113. def slot_transportLinkEnabled(self, clicked):
  114. if not self.host.is_engine_running():
  115. return
  116. def showEvent(self, event):
  117. self.refreshTransport(True)
  118. QDialog.showEvent(self, event)
  119. def refreshTransport(self, forced = False):
  120. if not self.isVisible():
  121. return
  122. if self.fSampleRate == 0.0 or not self.host.is_engine_running():
  123. return
  124. timeInfo = self.host.get_transport_info()
  125. playing = timeInfo['playing']
  126. frame = timeInfo['frame']
  127. bpm = timeInfo['bpm']
  128. if playing != self.fLastTransportState or forced:
  129. if playing:
  130. icon = getIcon("media-playback-pause")
  131. self.ui.b_play.setChecked(True)
  132. self.ui.b_play.setIcon(icon)
  133. #self.ui.b_play.setText(self.tr("&Pause"))
  134. else:
  135. icon = getIcon("media-playback-start")
  136. self.ui.b_play.setChecked(False)
  137. self.ui.b_play.setIcon(icon)
  138. #self.ui.b_play.setText(self.tr("&Play"))
  139. self.fLastTransportState = playing
  140. if frame != self.fLastTransportFrame or forced:
  141. self.fLastTransportFrame = frame
  142. time = frame / self.fSampleRate
  143. secs = time % 60
  144. mins = (time / 60) % 60
  145. hrs = (time / 3600) % 60
  146. self.ui.l_time_clock.setText("%02i:%02i:%02i" % (hrs, mins, secs))
  147. frame1 = frame % 1000
  148. frame2 = (frame / 1000) % 1000
  149. frame3 = (frame / 1000000) % 1000
  150. self.ui.l_time_frame.setText("%03i'%03i'%03i" % (frame3, frame2, frame1))
  151. bar = timeInfo['bar']
  152. beat = timeInfo['beat']
  153. tick = timeInfo['tick']
  154. self.ui.l_time_bbt.setText("%03i|%02i|%04i" % (bar, beat, tick))
  155. if bpm != self.fLastTransportBPM or forced:
  156. self.fLastTransportBPM = bpm
  157. if bpm > 0.0:
  158. self.ui.dsb_bpm.setValue(bpm)
  159. self.ui.dsb_bpm.setStyleSheet("")
  160. else:
  161. self.ui.dsb_bpm.setStyleSheet("QDoubleSpinBox { color: palette(mid); }")
  162. # --------------------------------------------------------------------------------------------------------
  163. # Engine callbacks
  164. @pyqtSlot(int, int, str)
  165. def slot_handleEngineStartedCallback(self, processMode, transportMode, driverName):
  166. self.fSampleRate = self.host.get_sample_rate()
  167. self.refreshTransport(True)
  168. self.ui.cb_transport_jack.setEnabled(driverName == "JACK")
  169. self.ui.cb_transport_jack.setChecked(transportMode == ENGINE_TRANSPORT_MODE_JACK)
  170. @pyqtSlot(float)
  171. def slot_handleSampleRateChangedCallback(self, newSampleRate):
  172. self.fSampleRate = newSampleRate
  173. self.refreshTransport(True)
  174. # ------------------------------------------------------------------------------------------------------------