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.

224 lines
8.1KB

  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.SampleRateChangedCallback.connect(self.slot_handleSampleRateChangedCallback)
  73. # --------------------------------------------------------------------------------------------------------
  74. # Button actions
  75. @pyqtSlot(bool)
  76. def slot_transportPlayPause(self, toggled):
  77. if self.host.isPlugin or not self.host.is_engine_running():
  78. return
  79. if toggled:
  80. self.host.transport_play()
  81. else:
  82. self.host.transport_pause()
  83. self.refreshTransport()
  84. @pyqtSlot()
  85. def slot_transportStop(self):
  86. if self.host.isPlugin or not self.host.is_engine_running():
  87. return
  88. self.host.transport_pause()
  89. self.host.transport_relocate(0)
  90. self.refreshTransport()
  91. @pyqtSlot()
  92. def slot_transportBackwards(self):
  93. if self.host.isPlugin or not self.host.is_engine_running():
  94. return
  95. newFrame = self.host.get_current_transport_frame() - 100000
  96. if newFrame < 0:
  97. newFrame = 0
  98. self.host.transport_relocate(newFrame)
  99. @pyqtSlot()
  100. def slot_transportForwards(self):
  101. if self.fSampleRate == 0.0 or self.host.isPlugin or not self.host.is_engine_running():
  102. return
  103. newFrame = self.host.get_current_transport_frame() + int(self.fSampleRate*2.5)
  104. self.host.transport_relocate(newFrame)
  105. @pyqtSlot(bool)
  106. def slot_transportJackEnabled(self, clicked):
  107. if not self.host.is_engine_running():
  108. return
  109. mode = ENGINE_TRANSPORT_MODE_JACK if clicked else ENGINE_TRANSPORT_MODE_INTERNAL
  110. self.host.set_engine_option(ENGINE_OPTION_TRANSPORT_MODE, mode, "")
  111. @pyqtSlot(bool)
  112. def slot_transportLinkEnabled(self, clicked):
  113. if not self.host.is_engine_running():
  114. return
  115. def showEvent(self, event):
  116. self.refreshTransport(True)
  117. QDialog.showEvent(self, event)
  118. def refreshTransport(self, forced = False):
  119. if not self.isVisible():
  120. return
  121. if self.fSampleRate == 0.0 or not self.host.is_engine_running():
  122. return
  123. timeInfo = self.host.get_transport_info()
  124. playing = timeInfo['playing']
  125. frame = timeInfo['frame']
  126. bpm = timeInfo['bpm']
  127. if playing != self.fLastTransportState or forced:
  128. if playing:
  129. icon = getIcon("media-playback-pause")
  130. self.ui.b_play.setChecked(True)
  131. self.ui.b_play.setIcon(icon)
  132. #self.ui.b_play.setText(self.tr("&Pause"))
  133. else:
  134. icon = getIcon("media-playback-start")
  135. self.ui.b_play.setChecked(False)
  136. self.ui.b_play.setIcon(icon)
  137. #self.ui.b_play.setText(self.tr("&Play"))
  138. self.fLastTransportState = playing
  139. if frame != self.fLastTransportFrame or forced:
  140. self.fLastTransportFrame = frame
  141. time = frame / self.fSampleRate
  142. secs = time % 60
  143. mins = (time / 60) % 60
  144. hrs = (time / 3600) % 60
  145. self.ui.l_time_clock.setText("%02i:%02i:%02i" % (hrs, mins, secs))
  146. frame1 = frame % 1000
  147. frame2 = (frame / 1000) % 1000
  148. frame3 = (frame / 1000000) % 1000
  149. self.ui.l_time_frame.setText("%03i'%03i'%03i" % (frame3, frame2, frame1))
  150. bar = timeInfo['bar']
  151. beat = timeInfo['beat']
  152. tick = timeInfo['tick']
  153. self.ui.l_time_bbt.setText("%03i|%02i|%04i" % (bar, beat, tick))
  154. if bpm != self.fLastTransportBPM or forced:
  155. self.fLastTransportBPM = bpm
  156. if bpm > 0.0:
  157. self.ui.dsb_bpm.setValue(bpm)
  158. self.ui.dsb_bpm.setStyleSheet("")
  159. else:
  160. self.ui.dsb_bpm.setStyleSheet("QDoubleSpinBox { color: palette(mid); }")
  161. # --------------------------------------------------------------------------------------------------------
  162. # Engine callbacks
  163. @pyqtSlot(int, int, str)
  164. def slot_handleEngineStartedCallback(self, processMode, transportMode, driverName):
  165. self.fSampleRate = self.host.get_sample_rate()
  166. self.refreshTransport(True)
  167. self.ui.cb_transport_jack.setEnabled(driverName == "JACK")
  168. self.ui.cb_transport_jack.setChecked(transportMode == ENGINE_TRANSPORT_MODE_JACK)
  169. @pyqtSlot(float)
  170. def slot_handleSampleRateChangedCallback(self, newSampleRate):
  171. self.fSampleRate = newSampleRate
  172. self.refreshTransport(True)
  173. # ------------------------------------------------------------------------------------------------------------