Collection of tools useful for audio production
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.

322 lines
9.9KB

  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # Common/Shared code
  4. # Copyright (C) 2010-2018 Filipe Coelho <falktx@falktx.com>
  5. #
  6. # This program is free software; you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation; either version 2 of the License, or
  9. # 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 COPYING file
  17. # ------------------------------------------------------------------------------------------------------------
  18. # Imports (Global)
  19. import os
  20. import sys
  21. from codecs import open as codecopen
  22. from unicodedata import normalize
  23. if True:
  24. from PyQt5.QtCore import pyqtSignal, qWarning
  25. from PyQt5.QtGui import QIcon
  26. from PyQt5.QtWidgets import QApplication, QFileDialog, QMessageBox
  27. else:
  28. from PyQt4.QtCore import pyqtSignal, qWarning
  29. from PyQt4.QtGui import QIcon
  30. from PyQt4.QtGui import QApplication, QFileDialog, QMessageBox
  31. # ------------------------------------------------------------------------------------------------------------
  32. # Set Platform
  33. if sys.platform == "darwin":
  34. from PyQt5.QtGui import qt_mac_set_menubar_icons
  35. qt_mac_set_menubar_icons(False)
  36. HAIKU = False
  37. LINUX = False
  38. MACOS = True
  39. WINDOWS = False
  40. elif "haiku" in sys.platform:
  41. HAIKU = True
  42. LINUX = False
  43. MACOS = False
  44. WINDOWS = False
  45. elif "linux" in sys.platform:
  46. HAIKU = False
  47. LINUX = True
  48. MACOS = False
  49. WINDOWS = False
  50. elif sys.platform in ("win32", "win64", "cygwin"):
  51. WINDIR = os.getenv("WINDIR")
  52. HAIKU = False
  53. LINUX = False
  54. MACOS = False
  55. WINDOWS = True
  56. else:
  57. HAIKU = False
  58. LINUX = False
  59. MACOS = False
  60. WINDOWS = False
  61. # ------------------------------------------------------------------------------------------------------------
  62. # Try Import Signal
  63. try:
  64. from signal import signal, SIGINT, SIGTERM, SIGUSR1, SIGUSR2
  65. haveSignal = True
  66. except:
  67. haveSignal = False
  68. # ------------------------------------------------------------------------------------------------------------
  69. # Safe exception hook, needed for PyQt5
  70. def sys_excepthook(typ, value, tback):
  71. return sys.__excepthook__(typ, value, tback)
  72. sys.excepthook = sys_excepthook
  73. # ------------------------------------------------------------------------------------------------------------
  74. # Set Version
  75. VERSION = "0.9.0"
  76. # ------------------------------------------------------------------------------------------------------------
  77. # Set Debug mode
  78. DEBUG = bool("-d" in sys.argv or "-debug" in sys.argv or "--debug" in sys.argv)
  79. # ------------------------------------------------------------------------------------------------------------
  80. # Global variables
  81. global gGui
  82. gGui = None
  83. # ------------------------------------------------------------------------------------------------------------
  84. # Set TMP
  85. TMP = os.getenv("TMP")
  86. if TMP is None:
  87. if WINDOWS:
  88. qWarning("TMP variable not set")
  89. TMP = os.path.join(WINDIR, "temp")
  90. else:
  91. TMP = "/tmp"
  92. # ------------------------------------------------------------------------------------------------------------
  93. # Set HOME
  94. HOME = os.getenv("HOME")
  95. if HOME is None:
  96. HOME = os.path.expanduser("~")
  97. if not WINDOWS:
  98. qWarning("HOME variable not set")
  99. if not os.path.exists(HOME):
  100. qWarning("HOME does not exist")
  101. HOME = TMP
  102. # ------------------------------------------------------------------------------------------------------------
  103. # Set PATH
  104. PATH = os.getenv("PATH")
  105. if PATH is None:
  106. qWarning("PATH variable not set")
  107. if MACOS:
  108. PATH = ("/opt/local/bin", "/usr/local/bin", "/usr/bin", "/bin")
  109. elif WINDOWS:
  110. PATH = (os.path.join(WINDIR, "system32"), WINDIR)
  111. else:
  112. PATH = ("/usr/local/bin", "/usr/bin", "/bin")
  113. else:
  114. PATH = PATH.split(os.pathsep)
  115. # ------------------------------------------------------------------------------------------------------------
  116. # Set PATH
  117. LIB_PATH = "lib"
  118. if os.path.isdir("/usr/lib64"):
  119. LIB_PATH = "lib64"
  120. # ------------------------------------------------------------------------------------------------------------
  121. # Remove/convert non-ascii chars from a string
  122. def asciiString(string):
  123. return normalize("NFKD", string).encode("ascii", "ignore").decode("utf-8")
  124. # ------------------------------------------------------------------------------------------------------------
  125. # Convert a ctypes c_char_p into a python string
  126. def cString(value):
  127. if not value:
  128. return ""
  129. if isinstance(value, str):
  130. return value
  131. return value.decode("utf-8", errors="ignore")
  132. # ------------------------------------------------------------------------------------------------------------
  133. # Check if a value is a number (float support)
  134. def isNumber(value):
  135. try:
  136. float(value)
  137. return True
  138. except:
  139. return False
  140. # ------------------------------------------------------------------------------------------------------------
  141. # Convert a value to a list
  142. def toList(value):
  143. if value is None:
  144. return []
  145. elif not isinstance(value, list):
  146. return [value]
  147. else:
  148. return value
  149. # ------------------------------------------------------------------------------------------------------------
  150. # Unicode open
  151. def uopen(filename, mode="r"):
  152. return codecopen(filename, encoding="utf-8", mode=mode)
  153. # ------------------------------------------------------------------------------------------------------------
  154. # QLineEdit and QPushButton combo
  155. def getAndSetPath(self_, currentPath, lineEdit):
  156. newPath = QFileDialog.getExistingDirectory(self_, self_.tr("Set Path"), currentPath, QFileDialog.ShowDirsOnly)
  157. if newPath:
  158. lineEdit.setText(newPath)
  159. return newPath
  160. # ------------------------------------------------------------------------------------------------------------
  161. # Get Icon from user theme, using our own as backup (Oxygen)
  162. def getIcon(icon, size=16):
  163. return QIcon.fromTheme(icon, QIcon(":/%ix%i/%s.png" % (size, size, icon)))
  164. # ------------------------------------------------------------------------------------------------------------
  165. # Custom MessageBox
  166. def CustomMessageBox(self_, icon, title, text, extraText="", buttons=QMessageBox.Yes|QMessageBox.No, defButton=QMessageBox.No):
  167. msgBox = QMessageBox(self_)
  168. msgBox.setIcon(icon)
  169. msgBox.setWindowTitle(title)
  170. msgBox.setText(text)
  171. msgBox.setInformativeText(extraText)
  172. msgBox.setStandardButtons(buttons)
  173. msgBox.setDefaultButton(defButton)
  174. return msgBox.exec_()
  175. # ------------------------------------------------------------------------------------------------------------
  176. # Signal handler
  177. def setUpSignals(self_):
  178. global gGui
  179. if gGui is None:
  180. gGui = self_
  181. if not haveSignal:
  182. return
  183. signal(SIGINT, signalHandler)
  184. signal(SIGTERM, signalHandler)
  185. signal(SIGUSR1, signalHandler)
  186. signal(SIGUSR2, signalHandler)
  187. gGui.SIGTERM.connect(closeWindowHandler)
  188. gGui.SIGUSR2.connect(showWindowHandler)
  189. def signalHandler(sig, frame):
  190. global gGui
  191. if gGui is None:
  192. return
  193. if sig in (SIGINT, SIGTERM):
  194. gGui.SIGTERM.emit()
  195. elif sig == SIGUSR1:
  196. gGui.SIGUSR1.emit()
  197. elif sig == SIGUSR2:
  198. gGui.SIGUSR2.emit()
  199. def closeWindowHandler():
  200. global gGui
  201. if gGui is None:
  202. return
  203. gGui.hide()
  204. gGui.close()
  205. QApplication.instance().quit()
  206. gGui = None
  207. def showWindowHandler():
  208. global gGui
  209. if gGui is None:
  210. return
  211. if gGui.isMaximized():
  212. gGui.showMaximized()
  213. else:
  214. gGui.showNormal()
  215. # ------------------------------------------------------------------------------------------------------------
  216. # Shared Icons
  217. def setIcons(self_, modes):
  218. global gGui
  219. if gGui is None:
  220. gGui = self_
  221. if "canvas" in modes:
  222. gGui.ui.act_canvas_arrange.setIcon(getIcon("view-sort-ascending"))
  223. gGui.ui.act_canvas_refresh.setIcon(getIcon("view-refresh"))
  224. gGui.ui.act_canvas_zoom_fit.setIcon(getIcon("zoom-fit-best"))
  225. gGui.ui.act_canvas_zoom_in.setIcon(getIcon("zoom-in"))
  226. gGui.ui.act_canvas_zoom_out.setIcon(getIcon("zoom-out"))
  227. gGui.ui.act_canvas_zoom_100.setIcon(getIcon("zoom-original"))
  228. gGui.ui.b_canvas_zoom_fit.setIcon(getIcon("zoom-fit-best"))
  229. gGui.ui.b_canvas_zoom_in.setIcon(getIcon("zoom-in"))
  230. gGui.ui.b_canvas_zoom_out.setIcon(getIcon("zoom-out"))
  231. gGui.ui.b_canvas_zoom_100.setIcon(getIcon("zoom-original"))
  232. if "jack" in modes:
  233. gGui.ui.act_jack_clear_xruns.setIcon(getIcon("edit-clear"))
  234. gGui.ui.act_jack_configure.setIcon(getIcon("configure"))
  235. gGui.ui.act_jack_render.setIcon(getIcon("media-record"))
  236. gGui.ui.b_jack_clear_xruns.setIcon(getIcon("edit-clear"))
  237. gGui.ui.b_jack_configure.setIcon(getIcon("configure"))
  238. gGui.ui.b_jack_render.setIcon(getIcon("media-record"))
  239. if "transport" in modes:
  240. gGui.ui.act_transport_play.setIcon(getIcon("media-playback-start"))
  241. gGui.ui.act_transport_stop.setIcon(getIcon("media-playback-stop"))
  242. gGui.ui.act_transport_backwards.setIcon(getIcon("media-seek-backward"))
  243. gGui.ui.act_transport_forwards.setIcon(getIcon("media-seek-forward"))
  244. gGui.ui.b_transport_play.setIcon(getIcon("media-playback-start"))
  245. gGui.ui.b_transport_stop.setIcon(getIcon("media-playback-stop"))
  246. gGui.ui.b_transport_backwards.setIcon(getIcon("media-seek-backward"))
  247. gGui.ui.b_transport_forwards.setIcon(getIcon("media-seek-forward"))
  248. if "misc" in modes:
  249. gGui.ui.act_quit.setIcon(getIcon("application-exit"))
  250. gGui.ui.act_configure.setIcon(getIcon("configure"))