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.

285 lines
9.7KB

  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. self.GetValue=self.slider.GetValue
  21. class CommsPanel(wx.Panel):
  22. """ OSC comms """
  23. def __init__(self, parent):
  24. wx.Panel.__init__(self, parent)
  25. sizer = wx.BoxSizer(wx.HORIZONTAL)
  26. label = wx.StaticText(self, label="Sync:")
  27. font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font)
  28. sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT|wx.EXPAND, 5)
  29. self.master = wx.ToggleButton(self, 1, "Master/Minion")
  30. sizer.Add(self.master, 0, wx.ALL, 3)
  31. self.ip=wx.TextCtrl(self, value="127.0.0.1")
  32. sizer.Add(self.ip, 0, wx.ALL, 3)
  33. self.port=wx.TextCtrl(self, value="9000")
  34. sizer.Add(self.port, 0, wx.ALL, 3)
  35. self.SetSizerAndFit(sizer)
  36. class InputPanel(wx.Panel):
  37. ''' Handle the ADC input settings '''
  38. def __init__(self, parent):
  39. ''' Constructor '''
  40. wx.Panel.__init__(self, parent)
  41. sizer = wx.BoxSizer(wx.HORIZONTAL)
  42. label = wx.StaticText(self, label="Line in:")
  43. font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font)
  44. sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5)
  45. self.gain = OSCSlider(self, "Gain", default_value=.5, align=False)
  46. sizer.Add(self.gain, 1, wx.ALL, 5)
  47. self.thru = OSCSlider(self, "Thru", default_value=.5, align=False)
  48. sizer.Add(self.thru, 1, wx.ALL, 5)
  49. self.mute = wx.ToggleButton(self, 1, "Mute")
  50. #self.mute.SetValue(1)
  51. sizer.Add(self.mute, 0)
  52. self.SetSizerAndFit(sizer)
  53. self.gain.Bind(wx.EVT_SCROLL, self.update)
  54. self.thru.Bind(wx.EVT_SCROLL, self.update)
  55. self.mute.Bind(wx.EVT_TOGGLEBUTTON, self.update)
  56. self.update()
  57. def update(self, evt=None):
  58. """ Send OSC messages """
  59. gain=self.gain.slider.GetValue()/100.
  60. thru=self.thru.slider.GetValue()/100.
  61. if self.mute.GetValue(): gain, thru = 0.,0.
  62. sendOSCSafe("/input", [gain, thru])
  63. class DelayPanel(wx.Panel):
  64. ''' Handle the ADC input settings '''
  65. def __init__(self, parent):
  66. ''' Constructor '''
  67. wx.Panel.__init__(self, parent)
  68. sizer = wx.BoxSizer(wx.VERTICAL)
  69. label = wx.StaticText(self, label="Delay lines:")
  70. font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font)
  71. sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5)
  72. self.delayTime=OSCSlider(self, "Delay time (s)", default_value=1, max_value=10)
  73. sizer.Add(self.delayTime, 0, wx.EXPAND|wx.ALL, 5)
  74. self.feedback=OSCSlider(self, "Feedback", default_value=.99)
  75. sizer.Add(self.feedback, 0, wx.EXPAND|wx.ALL, 5)
  76. self.metronome=wx.ToggleButton(self, 0, "Metronome")
  77. sizer.Add(self.metronome, 0, wx.EXPAND|wx.ALL, 5)
  78. self.SetSizerAndFit(sizer)
  79. self.delayTime.Bind(wx.EVT_SCROLL, self.update)
  80. self.feedback.Bind(wx.EVT_SCROLL, self.update)
  81. self.metronome.Bind(wx.EVT_TOGGLEBUTTON, self.switchMetronome)
  82. self.update(None)
  83. def update(self, evt):
  84. """ Send OSC messages """
  85. a=self.delayTime.slider.GetValue()/100.
  86. b=self.feedback.slider.GetValue()/100.
  87. sendOSCSafe("/delay", [a, b])
  88. def switchMetronome(self, evt):
  89. """ Send OSC messages """
  90. sendOSCSafe("/metronome", [int(self.metronome.GetValue())])
  91. class Channel(wx.Panel):
  92. """ A single channel """
  93. def __init__(self, parent, index):
  94. self.index=index
  95. wx.Panel.__init__(self, parent)
  96. sizer = wx.BoxSizer(wx.VERTICAL)
  97. label = wx.StaticText(self, label="CH%d" % self.index)
  98. font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font)
  99. sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5)
  100. self.gain = OSCSlider(self, "Gain", default_value=1, max_value=1.3, align=False)
  101. sizer.Add(self.gain, 0, wx.ALL|wx.EXPAND, 3)
  102. self.pan = OSCSlider(self, "Pan", default_value=0, min_value=-1, max_value=1, align=False)
  103. sizer.Add(self.pan, 0, wx.ALL|wx.EXPAND, 3)
  104. self.fxsend = OSCSlider(self, "Dry/Wet", default_value=0, min_value=0, max_value=1, align=False)
  105. sizer.Add(self.fxsend, 0, wx.ALL|wx.EXPAND, 3)
  106. self.record = wx.ToggleButton(self, 1, "Arm")
  107. sizer.Add(self.record, 0, wx.ALL|wx.EXPAND if index==0 else wx.ALL|wx.EXPAND, 3)
  108. self.mute = wx.ToggleButton(self, 1, "Mute")
  109. sizer.Add(self.mute, 0, wx.ALL|wx.EXPAND, 3)
  110. self.clear = wx.Button(self, 1, "Clear")
  111. sizer.Add(self.clear, 0, wx.ALL|wx.EXPAND, 3)
  112. choices=["1 bar", "2 bars", "4 bars", "Dephase"]
  113. self.speed= wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25,25))
  114. self.speed.SetValue("1 bar")
  115. sizer.Add(self.speed, 0, wx.ALL|wx.EXPAND, 3)
  116. self.SetSizerAndFit(sizer)
  117. self.gain.Bind(wx.EVT_SCROLL, self.update)
  118. self.pan.Bind(wx.EVT_SCROLL, self.update)
  119. self.mute.Bind(wx.EVT_TOGGLEBUTTON, self.update)
  120. self.update()
  121. def update(self, evt=None):
  122. gain=self.gain.GetValue()/100.
  123. pan=self.pan.GetValue()/100.
  124. if self.mute.GetValue(): gain=0.0;
  125. sendOSCSafe("/channel", [self.index, gain, pan])
  126. class Mixer(wx.Panel):
  127. ''' All the channels '''
  128. def __init__(self, parent):
  129. ''' Constructor '''
  130. wx.Panel.__init__(self, parent)
  131. sizer = wx.BoxSizer(wx.HORIZONTAL)
  132. self.channels=[]
  133. for i in range(4):
  134. c=Channel(self, index=i)
  135. c.record.Bind(wx.EVT_TOGGLEBUTTON, self.switch_record)
  136. c.record.index=i
  137. c.clear.Bind(wx.EVT_BUTTON, self.clear_channel)
  138. c.clear.index=i
  139. self.channels.append(c)
  140. sizer.Add(c, 1, wx.EXPAND)
  141. self.SetSizerAndFit(sizer)
  142. def switch_record(self, evt):
  143. """ Send OSC message to switch recording channel """
  144. index = evt.GetEventObject().index
  145. value = evt.GetEventObject().GetValue()
  146. for i, c in enumerate(self.channels):
  147. c.record.SetValue(0)
  148. self.channels[index].record.SetValue(value)
  149. sendOSCSafe("/arm", [index if value else -1])
  150. def clear_channel(self, evt):
  151. """ Send OSC message to clear a channel """
  152. index = evt.GetEventObject().index
  153. sendOSCSafe("/clear", [index])
  154. class FXPanel(wx.Panel):
  155. ''' Effects chain '''
  156. def __init__(self, parent):
  157. ''' Constructor '''
  158. wx.Panel.__init__(self, parent)
  159. sizer = wx.BoxSizer(wx.VERTICAL)
  160. label = wx.StaticText(self, label="FX:")
  161. font = label.GetFont(); font.SetWeight(wx.BOLD); label.SetFont(font)
  162. sizer.Add(label, 0, wx.TOP|wx.BOTTOM|wx.RIGHT, 5)
  163. choices=["Low pass filter", "High pass filter", "Reverb"]
  164. self.fxtype= wx.ComboBox(self, choices=choices, style=wx.CB_READONLY, size=(25,25))
  165. sizer.Add(self.fxtype, 0, wx.ALL|wx.EXPAND, 5)
  166. self.fxtype.SetValue(choices[0])
  167. self.delayTime=OSCSlider(self, "Strength", default_value=0)
  168. sizer.Add(self.delayTime, 0, wx.EXPAND|wx.ALL, 5)
  169. self.SetSizerAndFit(sizer)
  170. #self.update(None)
  171. """
  172. def update(self, evt):
  173. # Send OSC messages
  174. a=self.delayTime.slider.GetValue()/100.
  175. b=self.feedback.slider.GetValue()/100.
  176. sendOSCSafe("/delay", [a, b])
  177. """
  178. class MainGUI(wx.Frame):
  179. """ A simple GUI to talk to Chuck """
  180. def __init__(self):
  181. """ Constructor """
  182. # Build the interface
  183. self.app = wx.App(False)
  184. self.build()
  185. self.app.MainLoop()
  186. def build(self):
  187. """ Builds the various pieces of the GUI """
  188. wx.Frame.__init__(self, None, title="DELAY LORD")
  189. self.Bind(wx.EVT_CLOSE, self.quit)
  190. # The main sizer
  191. self.mainsizer = wx.BoxSizer(wx.VERTICAL)
  192. self.commsPanel = CommsPanel(self)
  193. self.mainsizer.Add(self.commsPanel, 0, wx.EXPAND|wx.ALL, 5)
  194. line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1)
  195. self.inputPanel = InputPanel(self)
  196. self.mainsizer.Add(self.inputPanel, 0, wx.EXPAND|wx.ALL, 5)
  197. line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1)
  198. self.delayPanel = DelayPanel(self)
  199. self.mainsizer.Add(self.delayPanel, 0, wx.EXPAND|wx.ALL, 5)
  200. line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1)
  201. self.mixer = Mixer(self)
  202. self.mainsizer.Add(self.mixer, 1, wx.EXPAND|wx.ALL, 5)
  203. line=wx.StaticLine(self); self.mainsizer.Add(line, 0, wx.EXPAND|wx.ALL, 1)
  204. self.fx = FXPanel(self)
  205. self.mainsizer.Add(self.fx, 0, wx.EXPAND|wx.ALL, 5)
  206. # Put things together
  207. self.SetSizerAndFit(self.mainsizer)
  208. self.Show()
  209. def populate_left_panel(self):
  210. """ Populate the left panel """
  211. # Status boxes
  212. def quit(self, *args):
  213. """ Close down gracefully, and then destroy the window """
  214. self.Destroy()
  215. if __name__ == "__main__":
  216. initOSCClient(ip="127.0.0.1", port=9000)
  217. g=MainGUI()
  218. closeOSC()