Sampler in ChucK
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.

356 lines
11KB

  1. from libs.simpleosc import *
  2. import wx
  3. def sendOSCSafe(channel, data):
  4. try:
  5. #print channel, data
  6. sendOSCMsg(channel, data)
  7. except OSCClientError:
  8. print "OSC comms error"
  9. class OSCSlider(wx.Panel):
  10. """ A GUI slider """
  11. def __init__(self, parent, label, min_value=0, max_value=1, default_value=0, align=True, rescale=100.):
  12. """ Constructor """
  13. self.rescale = rescale
  14. wx.Panel.__init__(self, parent)
  15. sizer = wx.BoxSizer(wx.HORIZONTAL)
  16. label = wx.StaticText(self, label=label, size=(100, 15) if align else None)
  17. sizer.Add(label, 0, wx.RIGHT, 10)
  18. self.slider = wx.Slider(self, value=default_value * self.rescale,
  19. minValue=min_value * self.rescale, maxValue=max_value * self.rescale)
  20. sizer.Add(self.slider, 1, wx.EXPAND)
  21. self.SetSizerAndFit(sizer)
  22. self.Bind = self.slider.Bind
  23. def GetValue(self):
  24. """ Make sure that we rescale """
  25. return self.slider.GetValue() / self.rescale
  26. class CommsPanel(wx.Panel):
  27. """ OSC comms """
  28. def __init__(self, parent):
  29. wx.Panel.__init__(self, parent)
  30. sizer = wx.BoxSizer(wx.HORIZONTAL)
  31. label = wx.StaticText(self, label="Sync:")
  32. font = label.GetFont()
  33. font.SetWeight(wx.BOLD)
  34. label.SetFont(font)
  35. sizer.Add(label, 0, wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND, 5)
  36. choices = ["Master", "Minion"]
  37. self.master = wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25, 25))
  38. sizer.Add(self.master, 1, wx.ALL, 3)
  39. self.master.SetValue(choices[0])
  40. self.ip = wx.TextCtrl(self, value="127.0.0.1")
  41. sizer.Add(self.ip, 0, wx.ALL, 3)
  42. self.port = wx.TextCtrl(self, value="9000")
  43. sizer.Add(self.port, 0, wx.ALL, 3)
  44. self.SetSizerAndFit(sizer)
  45. class InputPanel(wx.Panel):
  46. """ Handle the ADC input settings """
  47. def __init__(self, parent):
  48. """ Constructor """
  49. wx.Panel.__init__(self, parent)
  50. sizer = wx.BoxSizer(wx.HORIZONTAL)
  51. label = wx.StaticText(self, label="Input:")
  52. font = label.GetFont()
  53. font.SetWeight(wx.BOLD)
  54. label.SetFont(font)
  55. sizer.Add(label, 0, wx.TOP | wx.BOTTOM | wx.RIGHT, 5)
  56. self.gain = OSCSlider(self, "Gain", default_value=.5, max_value = 1.2, align=False)
  57. sizer.Add(self.gain, 1, wx.ALL, 5)
  58. self.thru = OSCSlider(self, "Thru", default_value=1, max_value = 1.2, align=False)
  59. sizer.Add(self.thru, 1, wx.ALL, 5)
  60. self.mute = wx.ToggleButton(self, 0, "Mute")
  61. # self.mute.SetValue(1)
  62. sizer.Add(self.mute, 0)
  63. self.SetSizerAndFit(sizer)
  64. self.gain.Bind(wx.EVT_SCROLL, self.update)
  65. self.thru.Bind(wx.EVT_SCROLL, self.update)
  66. self.mute.Bind(wx.EVT_TOGGLEBUTTON, self.update)
  67. self.update()
  68. def update(self, evt=None):
  69. """ Send OSC messages """
  70. gain = self.gain.GetValue()
  71. thru = self.thru.GetValue()
  72. if self.mute.GetValue():
  73. gain, thru = 0., 0.
  74. sendOSCSafe("/input", [gain, thru])
  75. class DelayPanel(wx.Panel):
  76. """ Handle the ADC input settings """
  77. def __init__(self, parent):
  78. """ Constructor """
  79. wx.Panel.__init__(self, parent)
  80. sizer = wx.BoxSizer(wx.HORIZONTAL)
  81. label = wx.StaticText(self, label="Loop:")
  82. font = label.GetFont()
  83. font.SetWeight(wx.BOLD)
  84. label.SetFont(font)
  85. sizer.Add(label, 0, wx.TOP | wx.BOTTOM | wx.RIGHT, 5)
  86. self.delayTime = OSCSlider(self, "Time", default_value=2, max_value=10, min_value=0.5, align=False)
  87. sizer.Add(self.delayTime, 1, wx.ALL, 5)
  88. self.feedback = OSCSlider(self, "Hold", default_value=.99, align=False)
  89. sizer.Add(self.feedback, 1, wx.ALL, 5)
  90. self.metronome = wx.ToggleButton(self, 0, "Metronome")
  91. sizer.Add(self.metronome, 0)
  92. self.SetSizerAndFit(sizer)
  93. self.delayTime.Bind(wx.EVT_SCROLL, self.update)
  94. self.feedback.Bind(wx.EVT_SCROLL, self.update)
  95. self.metronome.Bind(wx.EVT_TOGGLEBUTTON, self.switchMetronome)
  96. self.update(None)
  97. def update(self, evt):
  98. """ Send OSC messages """
  99. a = self.delayTime.GetValue()
  100. b = self.feedback.GetValue()
  101. sendOSCSafe("/delay", [a, b])
  102. def switchMetronome(self, evt):
  103. """ Send OSC messages """
  104. sendOSCSafe("/metronome", [int(self.metronome.GetValue())])
  105. class ButtonArray(wx.Panel):
  106. """ Handle the ADC input settings """
  107. def __init__(self, parent, index):
  108. wx.Panel.__init__(self, parent)
  109. w = 40
  110. sizer = wx.BoxSizer(wx.HORIZONTAL)
  111. self.record = wx.ToggleButton(self, 0, "Arm", size=(w, 25))
  112. sizer.Add(self.record, 1, wx.ALL, 0)
  113. self.mute = wx.ToggleButton(self, 0, "Mute", size=(w, 25))
  114. sizer.Add(self.mute, 1, wx.ALL, 0)
  115. self.clear = wx.Button(self, 0, "Clear", size=(w, 25))
  116. sizer.Add(self.clear, 1, wx.ALL, 0)
  117. self.buttons = (self.record, self.mute, self.clear)
  118. self.SetSizerAndFit(sizer)
  119. class Channel(wx.Panel):
  120. """ A single channel """
  121. def __init__(self, parent, index):
  122. self.index = index
  123. wx.Panel.__init__(self, parent)
  124. sizer = wx.BoxSizer(wx.VERTICAL)
  125. self.gain = OSCSlider(self, "Gain", default_value=1, max_value=1.3, align=False)
  126. sizer.Add(self.gain, 0, wx.ALL | wx.EXPAND, 3)
  127. self.pan = OSCSlider(self, "Pan", default_value=0, min_value=-1, max_value=1, align=False)
  128. sizer.Add(self.pan, 0, wx.ALL | wx.EXPAND, 3)
  129. self.fxsend = OSCSlider(self, "Dry/Wet", default_value=0, min_value=0, max_value=1, align=False)
  130. sizer.Add(self.fxsend, 0, wx.ALL | wx.EXPAND, 3)
  131. self.buttons = ButtonArray(self, index)
  132. self.record, self.mute, self.clear = self.buttons.buttons
  133. sizer.Add(self.buttons, 0, wx.ALL | wx.EXPAND, 3)
  134. choices = ["1 bar", "2 bars", "4 bars", "Dephase", "1/2 rate"]
  135. self.speed = wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25, 25))
  136. self.speed.SetValue(choices[0])
  137. sizer.Add(self.speed, 0, wx.ALL | wx.EXPAND, 3)
  138. choices = ["Live ->", "Live <->", "loop1.wav", "loop2.wav", "loop3.wav"]
  139. self.speed = wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25, 25))
  140. self.speed.SetValue(choices[0])
  141. sizer.Add(self.speed, 0, wx.ALL | wx.EXPAND, 3)
  142. self.SetSizerAndFit(sizer)
  143. self.gain.Bind(wx.EVT_SCROLL, self.update)
  144. self.pan.Bind(wx.EVT_SCROLL, self.update)
  145. self.fxsend.Bind(wx.EVT_SCROLL, self.update)
  146. self.mute.Bind(wx.EVT_TOGGLEBUTTON, self.update)
  147. self.update()
  148. def update(self, evt=None):
  149. gain = self.gain.GetValue()
  150. pan = self.pan.GetValue()
  151. fxsend = self.fxsend.GetValue()
  152. if self.mute.GetValue():
  153. gain = 0.0
  154. sendOSCSafe("/channel", [self.index, gain, pan, fxsend])
  155. class Mixer(wx.Panel):
  156. """ All the channels """
  157. def __init__(self, parent):
  158. """ Constructor """
  159. wx.Panel.__init__(self, parent)
  160. sizer = wx.BoxSizer(wx.HORIZONTAL)
  161. self.channels = []
  162. for i in range(4):
  163. c = Channel(self, index=i)
  164. c.record.Bind(wx.EVT_TOGGLEBUTTON, self.switch_record)
  165. c.record.index = i
  166. c.clear.Bind(wx.EVT_BUTTON, self.clear_channel)
  167. c.clear.index = i
  168. self.channels.append(c)
  169. sizer.Add(c, 1, wx.EXPAND)
  170. self.SetSizerAndFit(sizer)
  171. def switch_record(self, evt):
  172. """ Send OSC message to switch recording channel """
  173. index = evt.GetEventObject().index
  174. value = evt.GetEventObject().GetValue()
  175. for i, c in enumerate(self.channels):
  176. c.record.SetValue(0)
  177. self.channels[index].record.SetValue(value)
  178. sendOSCSafe("/arm", [index if value else -1])
  179. def clear_channel(self, evt):
  180. """ Send OSC message to clear a channel """
  181. index = evt.GetEventObject().index
  182. sendOSCSafe("/clear", [index])
  183. class FXPanel(wx.Panel):
  184. """ Effects chain """
  185. def __init__(self, parent):
  186. """ Constructor """
  187. wx.Panel.__init__(self, parent)
  188. sizer = wx.BoxSizer(wx.HORIZONTAL)
  189. label = wx.StaticText(self, label="FX:")
  190. font = label.GetFont()
  191. font.SetWeight(wx.BOLD)
  192. label.SetFont(font)
  193. sizer.Add(label, 0, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.RIGHT, 5)
  194. self.lpf = OSCSlider(self, "Lo-pass", default_value=1, align=False)
  195. sizer.Add(self.lpf, 2, wx.EXPAND | wx.ALL, 5)
  196. self.lpf.Bind(wx.EVT_SCROLL, self.update)
  197. self.hpf = OSCSlider(self, "Hi-pass", min_value=0, default_value=0, align=False)
  198. sizer.Add(self.hpf, 2, wx.EXPAND | wx.ALL, 5)
  199. self.hpf.Bind(wx.EVT_SCROLL, self.update)
  200. self.reverb = OSCSlider(self, "Reverb", default_value=.1, align=False)
  201. sizer.Add(self.reverb, 2, wx.EXPAND | wx.ALL, 5)
  202. self.reverb.Bind(wx.EVT_SCROLL, self.update)
  203. self.SetSizerAndFit(sizer)
  204. self.update(None)
  205. def update(self, evt):
  206. a = self.lpf.GetValue()
  207. a2 = self.hpf.GetValue()
  208. b = self.reverb.GetValue()
  209. sendOSCSafe("/fx", [a, a2, b])
  210. class OutputPanel(wx.Panel):
  211. """ Handle the ADC input settings """
  212. def __init__(self, parent):
  213. """ Constructor """
  214. wx.Panel.__init__(self, parent)
  215. sizer = wx.BoxSizer(wx.HORIZONTAL)
  216. label = wx.StaticText(self, label="Output:")
  217. font = label.GetFont()
  218. font.SetWeight(wx.BOLD)
  219. label.SetFont(font)
  220. sizer.Add(label, 0, wx.TOP | wx.BOTTOM | wx.RIGHT, 5)
  221. self.level = OSCSlider(self, "Level", default_value=.8, align=False)
  222. sizer.Add(self.level, 2, wx.EXPAND | wx.ALL, 5)
  223. self.level.Bind(wx.EVT_SCROLL, self.update)
  224. self.SetSizerAndFit(sizer)
  225. def update(self, evt):
  226. a = self.level.GetValue()
  227. sendOSCSafe("/master", [a])
  228. class MainGUI(wx.Frame):
  229. """ A simple GUI to talk to Chuck """
  230. def __init__(self):
  231. """ Constructor """
  232. # Build the interface
  233. self.app = wx.App(False)
  234. self.build()
  235. def run(self):
  236. self.app.MainLoop()
  237. def build(self):
  238. """ Builds the various pieces of the GUI """
  239. wx.Frame.__init__(self, None, title="DELAY LORD")
  240. self.Bind(wx.EVT_CLOSE, self.quit)
  241. # The main sizer
  242. self.mainsizer = wx.BoxSizer(wx.VERTICAL)
  243. self.components = []
  244. components = (CommsPanel, InputPanel, DelayPanel, Mixer, FXPanel, OutputPanel)
  245. for index, ctype in enumerate(components):
  246. if index>0: self.mainsizer.Add(wx.StaticLine(self), 0, wx.EXPAND | wx.ALL, 1)
  247. c = ctype(self)
  248. self.components.append(c)
  249. self.mainsizer.Add(c, 0, wx.EXPAND | wx.ALL, 5)
  250. self.SetSizerAndFit(self.mainsizer)
  251. self.Show()
  252. def populate_left_panel(self):
  253. """ Populate the left panel """
  254. # Status boxes
  255. def quit(self, *args):
  256. """ Close down gracefully, and then destroy the window """
  257. self.Destroy()
  258. if __name__ == "__main__":
  259. initOSCClient(ip="127.0.0.1", port=9000)
  260. g = MainGUI()
  261. g.run()
  262. closeOSC()