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.

327 lines
11KB

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