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.

347 lines
12KB

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