def __init__(self, parent, surface): scrolled.ScrolledPanel.__init__(self, parent, -1) self.SetBackgroundColour(BACKGROUND_COLOUR) self.parent = parent self.surface = surface self.type = 0 self.selected = 0 self.selectedOkToChange = True self.sndPath = "" self.sndDur = 0.0 self.amplitude = 1 self.nchnls = 2 self.samplingRate = 44100 self.fileformat = 0 self.sampletype = 0 self.tempState = None box = wx.BoxSizer(wx.VERTICAL) box.Add(wx.StaticText(self, -1, "Trajectories"), 0, wx.CENTER | wx.TOP, 3) typeBox = wx.BoxSizer(wx.HORIZONTAL) popupBox = wx.BoxSizer(wx.VERTICAL) self.trajType = wx.Choice(self, -1, choices=['Free', 'Circle', 'Oscil', 'Line']) self.trajType.SetSelection(0) popupBox.Add(self.trajType) typeBox.Add(popupBox, 0, wx.CENTER | wx.RIGHT, 5) # TODO: Check the size of this button on Windows and OSX self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize()) font = self.closedToggle.GetFont() if PLATFORM.startswith('linux') or PLATFORM == 'win32': font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) self.closedToggle.SetFont(font) typeBox.Add(self.closedToggle, wx.CENTER | wx.RIGHT, 5) box.Add(typeBox, 0, wx.CENTER | wx.ALL, 5) self.notebook = wx.Notebook(self, -1, style=wx.BK_DEFAULT | wx.EXPAND) self.notebook.SetBackgroundColour(BACKGROUND_COLOUR) self.drawing = DrawingParameters(self.notebook) self.playback = PlaybackParameters(self.notebook) self.notebook.AddPage(self.drawing, "Drawing") self.notebook.AddPage(self.playback, "Playback") box.Add(self.notebook, 0, wx.ALL, 5) # EQ eqTitle = wx.StaticText(self, id=-1, label="4 Bands Equalizer") box.Add(eqTitle, 0, wx.CENTER) eqFreqBox = wx.BoxSizer(wx.HORIZONTAL) self.knobEqF1 = ControlKnob(self, 40, 250, 100, label='Freq 1', outFunction=self.changeEqF1) eqFreqBox.Add(self.knobEqF1, 0, wx.LEFT | wx.RIGHT, 20) self.knobEqF1.setFloatPrecision(2) self.knobEqF2 = ControlKnob(self, 300, 1000, 500, label='Freq 2', outFunction=self.changeEqF2) eqFreqBox.Add(self.knobEqF2, 0, wx.LEFT | wx.RIGHT, 4) self.knobEqF2.setFloatPrecision(2) self.knobEqF3 = ControlKnob(self, 1200, 5000, 2000, label='Freq 3', outFunction=self.changeEqF3) eqFreqBox.Add(self.knobEqF3, 0, wx.LEFT | wx.RIGHT, 20) self.knobEqF3.setFloatPrecision(2) box.Add(eqFreqBox) eqGainBox = wx.BoxSizer(wx.HORIZONTAL) self.knobEqA1 = ControlKnob(self, -40, 18, 0, label='B1 gain', outFunction=self.changeEqA1) eqGainBox.Add(self.knobEqA1, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA2 = ControlKnob(self, -40, 18, 0, label='B2 gain', outFunction=self.changeEqA2) eqGainBox.Add(self.knobEqA2, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA3 = ControlKnob(self, -40, 18, 0, label='B3 gain', outFunction=self.changeEqA3) eqGainBox.Add(self.knobEqA3, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA4 = ControlKnob(self, -40, 18, 0, label='B4 gain', outFunction=self.changeEqA4) eqGainBox.Add(self.knobEqA4, 0, wx.LEFT | wx.RIGHT, 5) box.Add(eqGainBox) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) #Compress compTitle = wx.StaticText(self, id=-1, label="Dynamic Compressor") box.Add(compTitle, 0, wx.CENTER) cpKnobBox = wx.BoxSizer(wx.HORIZONTAL) self.knobComp1 = ControlKnob(self, -60, 0, -3, label='Thresh', outFunction=self.changeComp1) cpKnobBox.Add(self.knobComp1, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp2 = ControlKnob(self, 1, 10, 2, label='Ratio', outFunction=self.changeComp2) cpKnobBox.Add(self.knobComp2, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp3 = ControlKnob(self, 0.001, 0.5, 0.05, label='Rise', outFunction=self.changeComp3) cpKnobBox.Add(self.knobComp3, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp4 = ControlKnob(self, 0.01, 1, .2, label='Fall', outFunction=self.changeComp4) cpKnobBox.Add(self.knobComp4, 0, wx.LEFT | wx.RIGHT, 5) box.Add(cpKnobBox) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10) ampBox = wx.BoxSizer(wx.HORIZONTAL) self.sl_amp = ControlSlider(self, -60, 18, 0, size=(200, 16), outFunction=self.handleAmp) ampBox.Add(self.sl_amp, 0, wx.LEFT | wx.RIGHT, 5) box.Add(ampBox, 0, wx.LEFT | wx.RIGHT, 5) box.AddSpacer(10) self.meter = VuMeter(self, size=(200, 11)) self.meter.setNumSliders(self.nchnls) box.Add(self.meter, 0, wx.LEFT, 10) box.AddSpacer(5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Project Settings"), 0, wx.CENTER | wx.ALL, 5) projSettingsBox = wx.BoxSizer(wx.HORIZONTAL) srBox = wx.BoxSizer(wx.VERTICAL) srText = wx.StaticText(self, -1, "Rate") srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sr = wx.Choice(self, -1, choices=['44100', '48000', '96000'], size=(80, -1)) self.pop_sr.SetSelection(0) self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate) srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5) chnlsBox = wx.BoxSizer(wx.VERTICAL) chnlsText = wx.StaticText(self, -1, "Chnls") chnlsBox.Add(chnlsText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(60, -1), style=wx.TE_PROCESS_ENTER) self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls) chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5) projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) projSettingsBox.Add(chnlsBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(projSettingsBox, 0, wx.ALIGN_CENTER, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) soundBox = wx.BoxSizer(wx.HORIZONTAL) self.tog_audio = wx.ToggleButton(self, -1, "Start", size=(80, -1)) self.tog_audio.SetFont(font) self.tog_audio.Disable() soundBox.Add(self.tog_audio, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) box.Add(soundBox, 0, wx.CENTER | wx.ALL, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Record Settings"), 0, wx.CENTER | wx.ALL, 5) recSettingsBox = wx.BoxSizer(wx.HORIZONTAL) fileformatBox = wx.BoxSizer(wx.VERTICAL) fileformatText = wx.StaticText(self, -1, "Format") fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80, -1)) self.pop_fileformat.SetSelection(0) self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat) fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5) sampletypeBox = wx.BoxSizer(wx.VERTICAL) sampletypeText = wx.StaticText(self, -1, "Type") sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES) self.pop_sampletype.SetSelection(0) self.pop_sampletype.Bind(wx.EVT_CHOICE, self.handleSampleType) sampletypeBox.Add(self.pop_sampletype, 0, wx.LEFT | wx.RIGHT, 5) recSettingsBox.Add(fileformatBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) recSettingsBox.Add(sampletypeBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(recSettingsBox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) rec1Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_rec_folder = wx.TextCtrl(self, -1, "~/Desktop", size=(120, -1)) rec1Box.Add(self.tx_rec_folder, 0, wx.LEFT | wx.RIGHT, 10) self.but_folder = wx.ToggleButton(self, -1, "Choose", size=(65, -1)) self.but_folder.SetFont(font) rec1Box.Add(self.but_folder, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) rec2Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_output = wx.TextCtrl(self, -1, "snd", size=(120, -1)) rec2Box.Add(self.tx_output, 0, wx.LEFT | wx.RIGHT, 10) self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65, -1)) self.tog_record.SetFont(font) rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec2Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) self.Bind(wx.EVT_CHOICE, self.handleType, self.trajType) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleClosed, self.closedToggle) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleAudio, self.tog_audio) self.tx_output.Bind(wx.EVT_CHAR, self.handleOutput) self.tx_rec_folder.Bind(wx.EVT_CHAR, self.handleOutput) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleRecord, self.tog_record) self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder) self.SetAutoLayout(True) self.SetSizerAndFit(box) self.SetupScrolling(scroll_x=False)
def __init__(self, parent, surface): scrolled.ScrolledPanel.__init__(self, parent, -1) self.SetBackgroundColour(BACKGROUND_COLOUR) self.parent = parent self.surface = surface self.type = 0 self.selected = 0 self.selectedOkToChange = True self.sndPath = "" self.sndDur = 0.0 self.amplitude = 1 self.nchnls = 2 self.samplingRate = 44100 self.midiInterface = None self.fileformat = 0 self.sampletype = 0 self.tempState = None box = wx.BoxSizer(wx.VERTICAL) box.Add(wx.StaticText(self, -1, "Trajectories"), 0, wx.CENTER|wx.TOP, 3) typeBox = wx.BoxSizer(wx.HORIZONTAL) popupBox = wx.BoxSizer(wx.VERTICAL) self.trajType = wx.Choice(self, -1, choices = ['Free', 'Circle', 'Oscil', 'Line']) self.trajType.SetSelection(0) popupBox.Add(self.trajType) typeBox.Add(popupBox, 0, wx.CENTER|wx.RIGHT, 5) # TODO: Check the size of this button on Windows and OSX self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize()) font = self.closedToggle.GetFont() if PLATFORM in ['win32', 'linux2']: font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) self.closedToggle.SetFont(font) typeBox.Add(self.closedToggle, wx.CENTER|wx.RIGHT, 5 ) box.Add(typeBox, 0, wx.CENTER|wx.ALL, 5) self.notebook = wx.Notebook(self, -1, style=wx.BK_DEFAULT | wx.EXPAND) self.notebook.SetBackgroundColour(BACKGROUND_COLOUR) self.drawing = DrawingParameters(self.notebook) self.playback = PlaybackParameters(self.notebook) self.notebook.AddPage(self.drawing, "Drawing") self.notebook.AddPage(self.playback, "Playback") box.Add(self.notebook, 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10) ampBox = wx.BoxSizer(wx.HORIZONTAL) self.sl_amp = ControlSlider(self, -60, 18, 0, size=(200, 16), outFunction=self.handleAmp) ampBox.Add(self.sl_amp, 0, wx.LEFT | wx.RIGHT, 5) box.Add(ampBox, 0, wx.LEFT | wx.RIGHT, 5) box.AddSpacer(10) self.meter = VuMeter(self, size=(200,11)) self.meter.setNumSliders(self.nchnls) box.Add(self.meter, 0, wx.LEFT, 10) box.AddSpacer(5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Project Settings"), 0, wx.CENTER | wx.ALL, 5) projSettingsBox = wx.BoxSizer(wx.HORIZONTAL) srBox = wx.BoxSizer(wx.VERTICAL) srText = wx.StaticText(self, -1, "Sample Rate") srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sr = wx.Choice(self, -1, choices = ['44100', '48000', '96000'], size=(80,-1)) self.pop_sr.SetSelection(0) self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate) srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5) chnlsBox = wx.BoxSizer(wx.VERTICAL) chnlsText = wx.StaticText(self, -1, "Channels") chnlsBox.Add(chnlsText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(80, -1), style=wx.TE_PROCESS_ENTER) self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls) chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5) projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) projSettingsBox.Add(chnlsBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(projSettingsBox, 0, wx.ALIGN_CENTER, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) soundBox = wx.BoxSizer(wx.HORIZONTAL) self.tog_audio = wx.ToggleButton(self, -1, "Start", size=(80,-1)) self.tog_audio.SetFont(font) self.tog_audio.Disable() soundBox.Add(self.tog_audio, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) box.Add(soundBox, 0, wx.CENTER | wx.ALL, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Record Settings"), 0, wx.CENTER | wx.ALL, 5) recSettingsBox = wx.BoxSizer(wx.HORIZONTAL) fileformatBox = wx.BoxSizer(wx.VERTICAL) fileformatText = wx.StaticText(self, -1, "File Format") fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80,-1)) self.pop_fileformat.SetSelection(0) self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat) fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5) sampletypeBox = wx.BoxSizer(wx.VERTICAL) sampletypeText = wx.StaticText(self, -1, "Sample Type") sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES) self.pop_sampletype.SetSelection(0) self.pop_sampletype.Bind(wx.EVT_CHOICE, self.handleSampleType) sampletypeBox.Add(self.pop_sampletype, 0, wx.LEFT | wx.RIGHT, 5) recSettingsBox.Add(fileformatBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) recSettingsBox.Add(sampletypeBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(recSettingsBox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) rec1Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_rec_folder = wx.TextCtrl( self, -1, "~/Desktop", size=(120, -1)) rec1Box.Add(self.tx_rec_folder, 0, wx.LEFT | wx.RIGHT, 10) self.but_folder = wx.ToggleButton(self, -1, "Choose", size=(65,-1)) self.but_folder.SetFont(font) rec1Box.Add(self.but_folder, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) rec2Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_output = wx.TextCtrl( self, -1, "snd", size=(120, -1)) rec2Box.Add(self.tx_output, 0, wx.LEFT | wx.RIGHT, 10) self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65,-1)) self.tog_record.SetFont(font) rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec2Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) self.Bind(wx.EVT_CHOICE, self.handleType, self.trajType) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleClosed, self.closedToggle) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleAudio, self.tog_audio) self.tx_output.Bind(wx.EVT_CHAR, self.handleOutput) self.tx_rec_folder.Bind(wx.EVT_CHAR, self.handleOutput) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleRecord, self.tog_record) self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder) self.SetAutoLayout(True) self.SetSizer(box) self.SetBestSize() self.SetupScrolling(scroll_x = False)
class ControlPanel(scrolled.ScrolledPanel): def __init__(self, parent, surface): scrolled.ScrolledPanel.__init__(self, parent, -1) self.SetBackgroundColour(BACKGROUND_COLOUR) self.parent = parent self.surface = surface self.type = 0 self.selected = 0 self.selectedOkToChange = True self.sndPath = "" self.sndDur = 0.0 self.amplitude = 1 self.nchnls = 2 self.samplingRate = 44100 self.fileformat = 0 self.sampletype = 0 self.tempState = None box = wx.BoxSizer(wx.VERTICAL) box.Add(wx.StaticText(self, -1, "Trajectories"), 0, wx.CENTER | wx.TOP, 3) typeBox = wx.BoxSizer(wx.HORIZONTAL) popupBox = wx.BoxSizer(wx.VERTICAL) self.trajType = wx.Choice(self, -1, choices=['Free', 'Circle', 'Oscil', 'Line']) self.trajType.SetSelection(0) popupBox.Add(self.trajType) typeBox.Add(popupBox, 0, wx.CENTER | wx.RIGHT, 5) # TODO: Check the size of this button on Windows and OSX self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize()) font = self.closedToggle.GetFont() if PLATFORM.startswith('linux') or PLATFORM == 'win32': font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) self.closedToggle.SetFont(font) typeBox.Add(self.closedToggle, wx.CENTER | wx.RIGHT, 5) box.Add(typeBox, 0, wx.CENTER | wx.ALL, 5) self.notebook = wx.Notebook(self, -1, style=wx.BK_DEFAULT | wx.EXPAND) self.notebook.SetBackgroundColour(BACKGROUND_COLOUR) self.drawing = DrawingParameters(self.notebook) self.playback = PlaybackParameters(self.notebook) self.notebook.AddPage(self.drawing, "Drawing") self.notebook.AddPage(self.playback, "Playback") box.Add(self.notebook, 0, wx.ALL, 5) # EQ eqTitle = wx.StaticText(self, id=-1, label="4 Bands Equalizer") box.Add(eqTitle, 0, wx.CENTER) eqFreqBox = wx.BoxSizer(wx.HORIZONTAL) self.knobEqF1 = ControlKnob(self, 40, 250, 100, label='Freq 1', outFunction=self.changeEqF1) eqFreqBox.Add(self.knobEqF1, 0, wx.LEFT | wx.RIGHT, 20) self.knobEqF1.setFloatPrecision(2) self.knobEqF2 = ControlKnob(self, 300, 1000, 500, label='Freq 2', outFunction=self.changeEqF2) eqFreqBox.Add(self.knobEqF2, 0, wx.LEFT | wx.RIGHT, 4) self.knobEqF2.setFloatPrecision(2) self.knobEqF3 = ControlKnob(self, 1200, 5000, 2000, label='Freq 3', outFunction=self.changeEqF3) eqFreqBox.Add(self.knobEqF3, 0, wx.LEFT | wx.RIGHT, 20) self.knobEqF3.setFloatPrecision(2) box.Add(eqFreqBox) eqGainBox = wx.BoxSizer(wx.HORIZONTAL) self.knobEqA1 = ControlKnob(self, -40, 18, 0, label='B1 gain', outFunction=self.changeEqA1) eqGainBox.Add(self.knobEqA1, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA2 = ControlKnob(self, -40, 18, 0, label='B2 gain', outFunction=self.changeEqA2) eqGainBox.Add(self.knobEqA2, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA3 = ControlKnob(self, -40, 18, 0, label='B3 gain', outFunction=self.changeEqA3) eqGainBox.Add(self.knobEqA3, 0, wx.LEFT | wx.RIGHT, 5) self.knobEqA4 = ControlKnob(self, -40, 18, 0, label='B4 gain', outFunction=self.changeEqA4) eqGainBox.Add(self.knobEqA4, 0, wx.LEFT | wx.RIGHT, 5) box.Add(eqGainBox) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) #Compress compTitle = wx.StaticText(self, id=-1, label="Dynamic Compressor") box.Add(compTitle, 0, wx.CENTER) cpKnobBox = wx.BoxSizer(wx.HORIZONTAL) self.knobComp1 = ControlKnob(self, -60, 0, -3, label='Thresh', outFunction=self.changeComp1) cpKnobBox.Add(self.knobComp1, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp2 = ControlKnob(self, 1, 10, 2, label='Ratio', outFunction=self.changeComp2) cpKnobBox.Add(self.knobComp2, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp3 = ControlKnob(self, 0.001, 0.5, 0.05, label='Rise', outFunction=self.changeComp3) cpKnobBox.Add(self.knobComp3, 0, wx.LEFT | wx.RIGHT, 5) self.knobComp4 = ControlKnob(self, 0.01, 1, .2, label='Fall', outFunction=self.changeComp4) cpKnobBox.Add(self.knobComp4, 0, wx.LEFT | wx.RIGHT, 5) box.Add(cpKnobBox) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10) ampBox = wx.BoxSizer(wx.HORIZONTAL) self.sl_amp = ControlSlider(self, -60, 18, 0, size=(200, 16), outFunction=self.handleAmp) ampBox.Add(self.sl_amp, 0, wx.LEFT | wx.RIGHT, 5) box.Add(ampBox, 0, wx.LEFT | wx.RIGHT, 5) box.AddSpacer(10) self.meter = VuMeter(self, size=(200, 11)) self.meter.setNumSliders(self.nchnls) box.Add(self.meter, 0, wx.LEFT, 10) box.AddSpacer(5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Project Settings"), 0, wx.CENTER | wx.ALL, 5) projSettingsBox = wx.BoxSizer(wx.HORIZONTAL) srBox = wx.BoxSizer(wx.VERTICAL) srText = wx.StaticText(self, -1, "Rate") srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sr = wx.Choice(self, -1, choices=['44100', '48000', '96000'], size=(80, -1)) self.pop_sr.SetSelection(0) self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate) srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5) chnlsBox = wx.BoxSizer(wx.VERTICAL) chnlsText = wx.StaticText(self, -1, "Chnls") chnlsBox.Add(chnlsText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(60, -1), style=wx.TE_PROCESS_ENTER) self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls) chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5) projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) projSettingsBox.Add(chnlsBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(projSettingsBox, 0, wx.ALIGN_CENTER, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) soundBox = wx.BoxSizer(wx.HORIZONTAL) self.tog_audio = wx.ToggleButton(self, -1, "Start", size=(80, -1)) self.tog_audio.SetFont(font) self.tog_audio.Disable() soundBox.Add(self.tog_audio, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) box.Add(soundBox, 0, wx.CENTER | wx.ALL, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Record Settings"), 0, wx.CENTER | wx.ALL, 5) recSettingsBox = wx.BoxSizer(wx.HORIZONTAL) fileformatBox = wx.BoxSizer(wx.VERTICAL) fileformatText = wx.StaticText(self, -1, "Format") fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80, -1)) self.pop_fileformat.SetSelection(0) self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat) fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5) sampletypeBox = wx.BoxSizer(wx.VERTICAL) sampletypeText = wx.StaticText(self, -1, "Type") sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES) self.pop_sampletype.SetSelection(0) self.pop_sampletype.Bind(wx.EVT_CHOICE, self.handleSampleType) sampletypeBox.Add(self.pop_sampletype, 0, wx.LEFT | wx.RIGHT, 5) recSettingsBox.Add(fileformatBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) recSettingsBox.Add(sampletypeBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(recSettingsBox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) rec1Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_rec_folder = wx.TextCtrl(self, -1, "~/Desktop", size=(120, -1)) rec1Box.Add(self.tx_rec_folder, 0, wx.LEFT | wx.RIGHT, 10) self.but_folder = wx.ToggleButton(self, -1, "Choose", size=(65, -1)) self.but_folder.SetFont(font) rec1Box.Add(self.but_folder, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) rec2Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_output = wx.TextCtrl(self, -1, "snd", size=(120, -1)) rec2Box.Add(self.tx_output, 0, wx.LEFT | wx.RIGHT, 10) self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65, -1)) self.tog_record.SetFont(font) rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec2Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) self.Bind(wx.EVT_CHOICE, self.handleType, self.trajType) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleClosed, self.closedToggle) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleAudio, self.tog_audio) self.tx_output.Bind(wx.EVT_CHAR, self.handleOutput) self.tx_rec_folder.Bind(wx.EVT_CHAR, self.handleOutput) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleRecord, self.tog_record) self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder) self.SetAutoLayout(True) self.SetSizerAndFit(box) self.SetupScrolling(scroll_x=False) def changeEqF1(self, x): self.parent.sg_audio.setEqFreq(0, x) def changeEqF2(self, x): self.parent.sg_audio.setEqFreq(1, x) def changeEqF3(self, x): self.parent.sg_audio.setEqFreq(2, x) def getEqFreqs(self): return [ self.knobEqF1.GetValue(), self.knobEqF2.GetValue(), self.knobEqF3.GetValue() ] def setEqFreqs(self, freqs): self.knobEqF1.SetValue(freqs[0]) self.knobEqF2.SetValue(freqs[1]) self.knobEqF3.SetValue(freqs[2]) def changeEqA1(self, x): self.parent.sg_audio.setEqGain(0, math.pow(10.0, x * 0.05)) def changeEqA2(self, x): self.parent.sg_audio.setEqGain(1, math.pow(10.0, x * 0.05)) def changeEqA3(self, x): self.parent.sg_audio.setEqGain(2, math.pow(10.0, x * 0.05)) def changeEqA4(self, x): self.parent.sg_audio.setEqGain(3, math.pow(10.0, x * 0.05)) def getEqAmps(self): return [ self.knobEqA1.GetValue(), self.knobEqA2.GetValue(), self.knobEqA3.GetValue(), self.knobEqA4.GetValue() ] def setEqAmps(self, amps): self.knobEqA1.SetValue(amps[0]) self.knobEqA2.SetValue(amps[1]) self.knobEqA3.SetValue(amps[2]) self.knobEqA4.SetValue(amps[3]) def changeComp1(self, x): self.parent.sg_audio.setCompParam("thresh", x) def changeComp2(self, x): self.parent.sg_audio.setCompParam("ratio", x) def changeComp3(self, x): self.parent.sg_audio.setCompParam("risetime", x) def changeComp4(self, x): self.parent.sg_audio.setCompParam("falltime", x) def getCompValues(self): return [ self.knobComp1.GetValue(), self.knobComp2.GetValue(), self.knobComp3.GetValue(), self.knobComp4.GetValue() ] def setCompValues(self, vals): self.knobComp1.SetValue(vals[0]) self.knobComp2.SetValue(vals[1]) self.knobComp3.SetValue(vals[2]) self.knobComp4.SetValue(vals[3]) def checkEnableWidgets(self): if self.type == 0: self.closedToggle.Enable() else: self.closedToggle.Disable() if self.type == 2: self.drawing.sl_period.Enable() self.drawing.sl_scaling.Enable() else: self.drawing.sl_period.Disable() self.drawing.sl_scaling.Disable() # TODO: replace all these handle, get, set, with single event def handleType(self, event): self.processType(event.GetInt()) def getType(self): return self.type def setType(self, type): self.trajType.SetSelection(type) self.processType(type) def processType(self, type): self.type = type self.surface.setMode(type) self.checkEnableWidgets() def handleClosed(self, event): self.surface.setClosed(event.GetInt()) def getClosed(self): return self.closedToggle.GetValue() def setClosed(self, closed): self.closedToggle.SetValue(closed) self.surface.setClosed(closed) def handleCutoff(self, val): for traj in self.surface.getAllTrajectories(): traj.setFilterFreq(val) def getCutoff(self): return self.drawing.sl_cutoff.GetValue() def setCutoff(self, cutoff): self.drawing.sl_cutoff.SetValue(cutoff) for traj in self.surface.getAllTrajectories(): traj.setFilterFreq(cutoff) def handleQ(self, val): for traj in self.surface.getAllTrajectories(): traj.setFilterQ(val) def getQ(self): return self.drawing.sl_q.GetValue() def setQ(self, q): self.drawing.sl_q.SetValue(q) for traj in self.surface.getAllTrajectories(): traj.setFilterQ(q) def handlePeriod(self, val): self.surface.setOscilPeriod(val) def getPeriod(self): return self.surface.getOscilPeriod() def setPeriod(self, period): self.drawing.sl_period.SetValue(period) self.surface.setOscilPeriod(period) def handleScaling(self, val): self.surface.setOscilScaling(val) def getScaling(self): return self.surface.getOscilScaling() def setScaling(self, scaling): self.drawing.sl_scaling.SetValue(scaling) self.surface.setOscilScaling(scaling) def resetPlaybackSliders(self): selToMax = False if self.selected == MAX_STREAMS: self.selected = 0 selToMax = True timeSpeed = self.surface.getTrajectory(self.selected).getTimeSpeed() self.setTimerSpeed(timeSpeed) step = self.surface.getTrajectory(self.selected).getStep() self.setStep(step) amp = self.surface.getTrajectory(self.selected).getAmplitude() self.setTrajAmp(amp) if selToMax: self.selected = MAX_STREAMS self.surface.needBitmap = True def handleSelected(self, event): if event.GetInt() != self.selected: self.selected = event.GetInt() self.selectedOkToChange = False if self.selected == MAX_STREAMS: self.selectedOkToChange = False self.resetPlaybackSliders() def setSelected(self, selected): self.playback.tog_traj.SetSelection(selected) self.selected = selected self.surface.setSelectedById(selected) self.resetPlaybackSliders() def getSelected(self): return self.selected def handlePopupFocus(self, evt): self.selectedOkToChange = False evt.Skip() def handleTimerSpeed(self, val): if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setTimeSpeed(val) else: self.surface.getTrajectory(self.selected).setTimeSpeed(val) else: self.selectedOkToChange = True def setTimerSpeed(self, timeSpeed): self.playback.sl_timespeed.SetValue(timeSpeed, self.selectedOkToChange) def sendTrajSpeed(self, which, speed): self.parent.sg_audio.setMetroTime(which, speed * 0.001) def handleStep(self, val): if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setStep(val) else: self.surface.getTrajectory(self.selected).setStep(val) else: self.selectedOkToChange = True def setStep(self, step): self.playback.sl_step.SetValue(step, self.selectedOkToChange) def handleTrajAmp(self, val): val = pow(10.0, float(val) * 0.05) if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setAmplitude(val) self.parent.sg_audio.setTrajAmplitude(t.label - 1, val) else: self.surface.getTrajectory(self.selected).setAmplitude(val) self.parent.sg_audio.setTrajAmplitude(self.selected, val) else: self.selectedOkToChange = True def setTrajAmp(self, val): if val <= 0.0: val = 0.0001 self.playback.sl_amp.SetValue(20.0 * math.log10(val), self.selectedOkToChange) def handleAmp(self, val): self.amplitude = pow(10.0, float(val) * 0.05) self.sendAmp() def getAmp(self): return self.amplitude def setAmp(self, amp): if amp <= 0.0: amp = 0.0001 self.sl_amp.SetValue(20.0 * math.log10(amp)) self.amplitude = amp def sendAmp(self): self.parent.sg_audio.setGlobalAmp(self.amplitude) def handleLoad(self): dlg = wx.FileDialog(self, message="Choose a sound file", defaultDir=self.parent.lastAudioPath, wildcard=AUDIO_WILDCARD, style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: sndPath = dlg.GetPath() self.loadSound(ensureNFD(sndPath)) self.parent.lastAudioPath = os.path.split(sndPath)[0] dlg.Destroy() def handleInsert(self): ok = False dlg = wx.FileDialog(self, message="Choose a sound file to insert", defaultDir=self.parent.lastAudioPath, wildcard=AUDIO_WILDCARD, style=wx.FD_OPEN) if dlg.ShowModal() == wx.ID_OK: ok = True sndPath = dlg.GetPath() self.parent.lastAudioPath = os.path.split(sndPath)[0] dlg.Destroy() if ok: self.insertSound(ensureNFD(sndPath), True) def loadSound(self, sndPath, force=False): if sndPath: if os.path.isfile(sndPath): self.sndPath = sndPath self.parent.sg_audio.loadSnd(self.sndPath) chnls, samprate, dur = soundInfo(self.sndPath) self.sndDur = dur self.chnls = chnls self.sndInfoStr = u'Loaded sound: %s, Sr: %i Hz, Channels: %s, Duration: %.3f sec' % ( self.sndPath, int(samprate), chnls, dur) if self.parent.draw: if not self.sndPath in self.surface.bitmapDict.keys( ) or force: self.parent.log("Drawing waveform...") self.surface.analyse(self.sndPath) else: self.surface.list = self.surface.bitmapDict[ self.sndPath] self.surface.create_bitmap() self.logSndInfo() elif os.path.isfile( os.path.join(self.parent.currentPath, os.path.split(sndPath)[1])): self.loadSound( os.path.join(self.parent.currentPath, os.path.split(sndPath)[1]), force) elif ":\\" in sndPath: # Handle windows path... self.loadSound( os.path.join(self.parent.currentPath, sndPath.split("\\")[-1]), force) else: self.parent.log('Sound file "%s" does not exist!' % sndPath) else: self.parent.log("") def insertSound(self, sndPath, force=False): if not self.sndPath: self.loadSound(sndPath) return if sndPath: if os.path.isfile(sndPath): self.sndPath = "Mixed sound " + str(random.randint(0, 10000)) chnls, samprate, dur = soundInfo(sndPath) dlg = InsertDialog(self, -1, 'Insert sound settings', actual_dur=self.sndDur, snd_dur=dur) refpos = self.surface.GetPosition() refsize = self.surface.GetSize() dlgsize = dlg.GetSize() X = refpos[0] + (refsize[0] / 2 - dlgsize[0] / 2) Y = refpos[1] + (refsize[1] / 2 - dlgsize[1] / 2) dlg.SetPosition((X, Y)) if dlg.ShowModal() == wx.ID_OK: start, end, point, cross = dlg.getValues() ok = True else: ok = False dlg.Destroy() if not ok: return self.parent.sg_audio.insertSnd(sndPath, start, end, point, cross) self.sndDur = self.parent.sg_audio.getTableDuration() self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % ( self.sndPath, samprate, self.chnls, self.sndDur) if self.parent.draw: if not self.sndPath in self.surface.bitmapDict.keys( ) or force: self.parent.log("Drawing waveform...") self.surface.analyse(self.sndPath) else: self.surface.list = self.surface.bitmapDict[ self.sndPath] self.surface.create_bitmap() self.logSndInfo() elif os.path.isfile( os.path.join(self.parent.currentPath, os.path.split(sndPath)[1])): self.insertSound( os.path.join(self.parent.currentPath, os.path.split(sndPath)[1]), force) elif ":\\" in sndPath: # Handle windows path... self.insertSound( os.path.join(self.parent.currentPath, sndPath.split("\\")[-1]), force) else: self.parent.log('Sound file "%s" does not exist!' % sndPath) def drawWaveform(self): if self.surface.sndBitmap and self.parent.draw: self.surface.analyse(self.sndPath) def getNchnls(self): return self.nchnls def setNchnls(self, x): if x != self.nchnls: self.nchnls = x self.tx_chnls.SetValue(str(x)) self.meter.setNumSliders(self.nchnls) self.shutdownServer() self.bootServer() def handleNchnls(self, event): x = int(self.tx_chnls.GetValue()) if x != self.nchnls: status, path = self.parent.checkForMixedSound() if not status: self.tx_chnls.SetValue(str(self.nchnls)) return if "Mixed sound" in self.sndPath: self.sndPath = path self.nchnls = x self.meter.setNumSliders(self.nchnls) self.shutdownServer() self.bootServer() def getSamplingRate(self): return self.samplingRate def setSamplingRate(self, x): SR = {44100: 0, 48000: 1, 96000: 2} if x != self.samplingRate: self.samplingRate = x self.pop_sr.SetSelection(SR[self.samplingRate]) self.shutdownServer() self.bootServer() def handleSamplingRate(self, event): SR = {0: 44100, 1: 48000, 2: 96000} x = SR[event.GetInt()] if x != self.samplingRate: status, path = self.parent.checkForMixedSound() if not status: SR = {44100: 0, 48000: 1, 96000: 2} self.pop_sr.SetSelection(SR[self.samplingRate]) return if "Mixed sound" in self.sndPath: self.sndPath = path self.samplingRate = x self.shutdownServer() self.bootServer() def getFileFormat(self): return self.fileformat def setFileFormat(self, x): self.fileformat = x self.pop_fileformat.SetSelection(self.fileformat) def handleFileFormat(self, event): self.fileformat = event.GetInt() def getSampleType(self): return self.sampletype def setSampleType(self, x): self.sampletype = x self.pop_sampletype.SetSelection(self.sampletype) def handleSampleType(self, event): self.sampletype = event.GetInt() def bootServer(self): self.parent.sg_audio.boot(self.parent.audioDriver, self.nchnls, self.samplingRate) self.tog_audio.Enable() if self.sndPath != "" and self.tempState == None: self.loadSound(self.sndPath) if self.tempState != None: self.parent.setState(self.tempState) self.tempState = None def shutdownServer(self): self.tempState = self.parent.getState() self.parent.sg_audio.shutdown() self.tog_audio.Disable() self.surface.Refresh() def handleAudio(self, event): if event.GetInt() == 1: if self.sndPath == "": self.parent.log('*** No sound loaded! ***') self.tog_audio.SetValue(0) self.parent.menu.Check(7, False) else: self.tx_chnls.Disable() self.tx_chnls.SetBackgroundColour("#EEEEEE") self.pop_sr.Disable() self.parent.enableDrivers(False) self.tog_audio.SetLabel('Stop') self.tog_audio.SetValue(1) self.parent.menu.Check(7, True) for t in self.surface.getAllTrajectories(): t.initCounter() self.parent.sg_audio.start() else: self.tx_chnls.Enable() self.tx_chnls.SetBackgroundColour("#FFFFFF") self.pop_sr.Enable() self.parent.enableDrivers(True) self.tog_audio.SetLabel('Start') self.tog_audio.SetValue(0) self.parent.menu.Check(7, False) self.tog_record.SetValue(0) self.tog_record.SetLabel('Start Rec') self.parent.sg_audio.stop() def handleOutput(self, event): key = event.GetKeyCode() if key == wx.WXK_TAB or key == wx.WXK_RETURN: self.surface.SetFocus() event.Skip() def setRecordFolder(self, str): self.tx_rec_folder.SetValue(str) def setRecordFilename(self, str): self.tx_output.SetValue(str) def handleRecord(self, event): if event.GetInt() == 1: folder = self.tx_rec_folder.GetValue() if folder.startswith("~"): folder = folder.replace("~", os.path.expanduser("~"), 1) if os.path.isdir(folder): filename = os.path.join(folder, self.tx_output.GetValue()) else: filename = os.path.join(os.path.expanduser('~'), "Desktop", self.tx_output.GetValue()) self.parent.sg_audio.recStart(filename, self.fileformat, self.sampletype) self.tog_record.SetLabel('Stop Rec') else: self.tog_record.SetLabel('Start Rec') self.parent.sg_audio.recStop() def chooseRecFolder(self, evt): dlg = wx.DirDialog( self, message="Choose a folder to save Soundgrain's output sounds...", defaultPath=os.path.expanduser("~")) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.tx_rec_folder.SetValue(ensureNFD(path)) dlg.Destroy() self.but_folder.SetValue(0) def logSndInfo(self): self.parent.log(self.sndInfoStr)
class ControlPanel(scrolled.ScrolledPanel): def __init__(self, parent, surface): scrolled.ScrolledPanel.__init__(self, parent, -1) self.SetBackgroundColour(BACKGROUND_COLOUR) self.parent = parent self.surface = surface self.type = 0 self.selected = 0 self.selectedOkToChange = True self.sndPath = "" self.sndDur = 0.0 self.amplitude = 1 self.nchnls = 2 self.samplingRate = 44100 self.midiInterface = None self.fileformat = 0 self.sampletype = 0 self.tempState = None box = wx.BoxSizer(wx.VERTICAL) box.Add(wx.StaticText(self, -1, "Trajectories"), 0, wx.CENTER|wx.TOP, 3) typeBox = wx.BoxSizer(wx.HORIZONTAL) popupBox = wx.BoxSizer(wx.VERTICAL) self.trajType = wx.Choice(self, -1, choices = ['Free', 'Circle', 'Oscil', 'Line']) self.trajType.SetSelection(0) popupBox.Add(self.trajType) typeBox.Add(popupBox, 0, wx.CENTER|wx.RIGHT, 5) # TODO: Check the size of this button on Windows and OSX self.closedToggle = wx.ToggleButton(self, -1, 'Closed', size=self.trajType.GetSize()) font = self.closedToggle.GetFont() if PLATFORM in ['win32', 'linux2']: font = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.NORMAL, wx.NORMAL) self.closedToggle.SetFont(font) typeBox.Add(self.closedToggle, wx.CENTER|wx.RIGHT, 5 ) box.Add(typeBox, 0, wx.CENTER|wx.ALL, 5) self.notebook = wx.Notebook(self, -1, style=wx.BK_DEFAULT | wx.EXPAND) self.notebook.SetBackgroundColour(BACKGROUND_COLOUR) self.drawing = DrawingParameters(self.notebook) self.playback = PlaybackParameters(self.notebook) self.notebook.AddPage(self.drawing, "Drawing") self.notebook.AddPage(self.playback, "Playback") box.Add(self.notebook, 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Global amplitude (dB)"), 0, wx.LEFT | wx.TOP, 10) ampBox = wx.BoxSizer(wx.HORIZONTAL) self.sl_amp = ControlSlider(self, -60, 18, 0, size=(200, 16), outFunction=self.handleAmp) ampBox.Add(self.sl_amp, 0, wx.LEFT | wx.RIGHT, 5) box.Add(ampBox, 0, wx.LEFT | wx.RIGHT, 5) box.AddSpacer(10) self.meter = VuMeter(self, size=(200,11)) self.meter.setNumSliders(self.nchnls) box.Add(self.meter, 0, wx.LEFT, 10) box.AddSpacer(5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Project Settings"), 0, wx.CENTER | wx.ALL, 5) projSettingsBox = wx.BoxSizer(wx.HORIZONTAL) srBox = wx.BoxSizer(wx.VERTICAL) srText = wx.StaticText(self, -1, "Sample Rate") srBox.Add(srText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sr = wx.Choice(self, -1, choices = ['44100', '48000', '96000'], size=(80,-1)) self.pop_sr.SetSelection(0) self.pop_sr.Bind(wx.EVT_CHOICE, self.handleSamplingRate) srBox.Add(self.pop_sr, 0, wx.LEFT | wx.RIGHT, 5) chnlsBox = wx.BoxSizer(wx.VERTICAL) chnlsText = wx.StaticText(self, -1, "Channels") chnlsBox.Add(chnlsText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.tx_chnls = wx.TextCtrl(self, -1, "2", size=(80, -1), style=wx.TE_PROCESS_ENTER) self.tx_chnls.Bind(wx.EVT_TEXT_ENTER, self.handleNchnls) chnlsBox.Add(self.tx_chnls, 0, wx.LEFT | wx.RIGHT, 5) projSettingsBox.Add(srBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) projSettingsBox.Add(chnlsBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(projSettingsBox, 0, wx.ALIGN_CENTER, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) soundBox = wx.BoxSizer(wx.HORIZONTAL) self.tog_audio = wx.ToggleButton(self, -1, "Start", size=(80,-1)) self.tog_audio.SetFont(font) self.tog_audio.Disable() soundBox.Add(self.tog_audio, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) box.Add(soundBox, 0, wx.CENTER | wx.ALL, 5) box.Add(wx.StaticLine(self, size=(210, 1)), 0, wx.ALL, 5) box.Add(wx.StaticText(self, -1, "Record Settings"), 0, wx.CENTER | wx.ALL, 5) recSettingsBox = wx.BoxSizer(wx.HORIZONTAL) fileformatBox = wx.BoxSizer(wx.VERTICAL) fileformatText = wx.StaticText(self, -1, "File Format") fileformatBox.Add(fileformatText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_fileformat = wx.Choice(self, -1, choices=EXPORT_FORMATS, size=(80,-1)) self.pop_fileformat.SetSelection(0) self.pop_fileformat.Bind(wx.EVT_CHOICE, self.handleFileFormat) fileformatBox.Add(self.pop_fileformat, 0, wx.LEFT | wx.RIGHT, 5) sampletypeBox = wx.BoxSizer(wx.VERTICAL) sampletypeText = wx.StaticText(self, -1, "Sample Type") sampletypeBox.Add(sampletypeText, 0, wx.CENTER | wx.LEFT | wx.RIGHT, 5) self.pop_sampletype = wx.Choice(self, -1, choices=EXPORT_TYPES) self.pop_sampletype.SetSelection(0) self.pop_sampletype.Bind(wx.EVT_CHOICE, self.handleSampleType) sampletypeBox.Add(self.pop_sampletype, 0, wx.LEFT | wx.RIGHT, 5) recSettingsBox.Add(fileformatBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) recSettingsBox.Add(sampletypeBox, 0, wx.LEFT | wx.RIGHT | wx.BOTTOM, 5) box.Add(recSettingsBox, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) rec1Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_rec_folder = wx.TextCtrl( self, -1, "~/Desktop", size=(120, -1)) rec1Box.Add(self.tx_rec_folder, 0, wx.LEFT | wx.RIGHT, 10) self.but_folder = wx.ToggleButton(self, -1, "Choose", size=(65,-1)) self.but_folder.SetFont(font) rec1Box.Add(self.but_folder, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) rec2Box = wx.BoxSizer(wx.HORIZONTAL) self.tx_output = wx.TextCtrl( self, -1, "snd", size=(120, -1)) rec2Box.Add(self.tx_output, 0, wx.LEFT | wx.RIGHT, 10) self.tog_record = wx.ToggleButton(self, -1, "Start Rec", size=(65,-1)) self.tog_record.SetFont(font) rec2Box.Add(self.tog_record, 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND | wx.RIGHT, 10) box.Add(wx.StaticText(self, -1, "Destination"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec1Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) box.Add(wx.StaticText(self, -1, "Filename"), 0, wx.LEFT | wx.RIGHT, 17) box.Add(rec2Box, 0, wx.EXPAND | wx.BOTTOM | wx.LEFT | wx.RIGHT, 5) self.Bind(wx.EVT_CHOICE, self.handleType, self.trajType) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleClosed, self.closedToggle) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleAudio, self.tog_audio) self.tx_output.Bind(wx.EVT_CHAR, self.handleOutput) self.tx_rec_folder.Bind(wx.EVT_CHAR, self.handleOutput) self.Bind(wx.EVT_TOGGLEBUTTON, self.handleRecord, self.tog_record) self.Bind(wx.EVT_TOGGLEBUTTON, self.chooseRecFolder, self.but_folder) self.SetAutoLayout(True) self.SetSizer(box) self.SetBestSize() self.SetupScrolling(scroll_x = False) def checkEnableWidgets(self): if self.type == 0: self.closedToggle.Enable() else: self.closedToggle.Disable() if self.type == 2: self.drawing.sl_period.Enable() self.drawing.sl_scaling.Enable() else: self.drawing.sl_period.Disable() self.drawing.sl_scaling.Disable() # TODO: replace all these handle, get, set, with single event def handleType(self, event): self.processType(event.GetInt()) def getType(self): return self.type def setType(self, type): self.trajType.SetSelection(type) self.processType(type) def processType(self, type): self.type = type self.surface.setMode(type) self.checkEnableWidgets() def handleClosed(self, event): self.surface.setClosed(event.GetInt()) def getClosed(self): return self.closedToggle.GetValue() def setClosed(self, closed): self.closedToggle.SetValue(closed) self.surface.setClosed(closed) def handleCutoff(self, val): for traj in self.surface.getAllTrajectories(): traj.setFilterFreq(val) def getCutoff(self): return self.drawing.sl_cutoff.GetValue() def setCutoff(self, cutoff): self.drawing.sl_cutoff.SetValue(cutoff) for traj in self.surface.getAllTrajectories(): traj.setFilterFreq(cutoff) def handleQ(self, val): for traj in self.surface.getAllTrajectories(): traj.setFilterQ(val) def getQ(self): return self.drawing.sl_q.GetValue() def setQ(self, q): self.drawing.sl_q.SetValue(q) for traj in self.surface.getAllTrajectories(): traj.setFilterQ(q) def handlePeriod(self, val): self.surface.setOscilPeriod(val) def getPeriod(self): return self.surface.getOscilPeriod() def setPeriod(self, period): self.drawing.sl_period.SetValue(period) self.surface.setOscilPeriod(period) def handleScaling(self, val): self.surface.setOscilScaling(val) def getScaling(self): return self.surface.getOscilScaling() def setScaling(self, scaling): self.drawing.sl_scaling.SetValue(scaling) self.surface.setOscilScaling(scaling) def resetPlaybackSliders(self): selToMax = False if self.selected == MAX_STREAMS: self.selected = 0 selToMax = True timeSpeed = self.surface.getTrajectory(self.selected).getTimeSpeed() self.setTimerSpeed(timeSpeed) step = self.surface.getTrajectory(self.selected).getStep() self.setStep(step) amp = self.surface.getTrajectory(self.selected).getAmplitude() self.setTrajAmp(amp) if selToMax: self.selected = MAX_STREAMS self.surface.needBitmap = True def handleSelected(self, event): if event.GetInt() != self.selected: self.selected = event.GetInt() self.selectedOkToChange = False if self.selected == MAX_STREAMS: self.selectedOkToChange = False self.resetPlaybackSliders() def setSelected(self, selected): self.playback.tog_traj.SetSelection(selected) self.selected = selected self.surface.setSelectedById(selected) self.resetPlaybackSliders() def getSelected(self): return self.selected def handlePopupFocus(self, evt): self.selectedOkToChange = False evt.Skip() def handleTimerSpeed(self, val): if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setTimeSpeed(val) else: self.surface.getTrajectory(self.selected).setTimeSpeed(val) else: self.selectedOkToChange = True def setTimerSpeed(self, timeSpeed): self.playback.sl_timespeed.SetValue(timeSpeed, self.selectedOkToChange) def sendTrajSpeed(self, which, speed): self.parent.sg_audio.setMetroTime(which, speed * 0.001) def handleStep(self, val): if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setStep(val) else: self.surface.getTrajectory(self.selected).setStep(val) else: self.selectedOkToChange = True def setStep(self, step): self.playback.sl_step.SetValue(step, self.selectedOkToChange) def handleTrajAmp(self, val): val = pow(10.0, float(val) * 0.05) if self.selectedOkToChange: if self.selected == MAX_STREAMS: for t in self.surface.getActiveTrajectories(): t.setAmplitude(val) self.parent.sg_audio.setTrajAmplitude(t.label-1, val) else: self.surface.getTrajectory(self.selected).setAmplitude(val) self.parent.sg_audio.setTrajAmplitude(self.selected, val) else: self.selectedOkToChange = True def setTrajAmp(self, val): if val <= 0.0: val = 0.0001 self.playback.sl_amp.SetValue(20.0 * math.log10(val), self.selectedOkToChange) def handleAmp(self, val): self.amplitude = pow(10.0, float(val) * 0.05) self.sendAmp() def getAmp(self): return self.amplitude def setAmp(self, amp): if amp <= 0.0: amp = 0.0001 self.sl_amp.SetValue(20.0 * math.log10(amp)) self.amplitude = amp def sendAmp(self): self.parent.sg_audio.setGlobalAmp(self.amplitude) def handleLoad(self): dlg = wx.FileDialog(self, message="Choose a sound file", wildcard=AUDIO_WILDCARD, style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: sndPath = dlg.GetPath() self.loadSound(ensureNFD(sndPath)) dlg.Destroy() def handleInsert(self): ok = False dlg = wx.FileDialog(self, message="Choose a sound file to insert", wildcard=AUDIO_WILDCARD, style=wx.OPEN) if dlg.ShowModal() == wx.ID_OK: ok = True sndPath = dlg.GetPath() dlg.Destroy() if ok: self.insertSound(ensureNFD(sndPath), True) def loadSound(self, sndPath, force=False): if sndPath: if os.path.isfile(sndPath): self.sndPath = sndPath self.parent.sg_audio.loadSnd(toSysEncoding(self.sndPath)) chnls, samprate, dur = soundInfo(toSysEncoding(self.sndPath)) self.sndDur = dur self.chnls = chnls self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % (self.sndPath, samprate, chnls, dur) if self.parent.draw: if not self.sndPath in self.surface.bitmapDict.keys() or force: self.parent.log("Drawing waveform...") self.surface.analyse(self.sndPath) else: self.surface.list = self.surface.bitmapDict[self.sndPath] self.surface.create_bitmap() self.logSndInfo() elif os.path.isfile(os.path.join(self.parent.currentPath, os.path.split(sndPath)[1])): self.loadSound(os.path.join(self.parent.currentPath, os.path.split(sndPath)[1]), force) elif ":\\" in sndPath: # Handle windows path... self.loadSound(os.path.join(self.parent.currentPath, sndPath.split("\\")[-1]), force) else: self.parent.log('Sound file "%s" does not exist!' % sndPath) else: self.parent.log("") def insertSound(self, sndPath, force=False): if not self.sndPath: self.loadSound(sndPath) return if sndPath: if os.path.isfile(sndPath): self.sndPath = "Mixed sound " + str(random.randint(0, 10000)) chnls, samprate, dur = soundInfo(toSysEncoding(sndPath)) dlg = InsertDialog(self, -1, 'Insert sound settings', actual_dur=self.sndDur, snd_dur=dur) refpos = self.surface.GetPosition() refsize = self.surface.GetSize() dlgsize = dlg.GetSize() X = refpos[0] + (refsize[0] / 2 - dlgsize[0] / 2) Y = refpos[1] + (refsize[1] / 2 - dlgsize[1] / 2) dlg.SetPosition((X,Y)) if dlg.ShowModal() == wx.ID_OK: start, end, point, cross = dlg.getValues() ok = True else: ok = False dlg.Destroy() if not ok: return self.parent.sg_audio.insertSnd(toSysEncoding(sndPath), start, end, point, cross) self.sndDur = self.parent.sg_audio.getTableDuration() self.sndInfoStr = u'Loaded sound: %s, Sr: %s Hz, Channels: %s, Duration: %s sec' % (self.sndPath, samprate, self.chnls, self.sndDur) if self.parent.draw: if not self.sndPath in self.surface.bitmapDict.keys() or force: self.parent.log("Drawing waveform...") self.surface.analyse(self.sndPath) else: self.surface.list = self.surface.bitmapDict[self.sndPath] self.surface.create_bitmap() self.logSndInfo() elif os.path.isfile(os.path.join(self.parent.currentPath, os.path.split(sndPath)[1])): self.insertSound(os.path.join(self.parent.currentPath, os.path.split(sndPath)[1]), force) elif ":\\" in sndPath: # Handle windows path... self.insertSound(os.path.join(self.parent.currentPath, sndPath.split("\\")[-1]), force) else: self.parent.log('Sound file "%s" does not exist!' % sndPath) def drawWaveform(self): if self.surface.sndBitmap and self.parent.draw: self.surface.analyse(self.sndPath) def getNchnls(self): return self.nchnls def setNchnls(self, x): if x != self.nchnls: self.nchnls = x self.tx_chnls.SetValue(str(x)) self.meter.setNumSliders(self.nchnls) self.shutdownServer() self.bootServer() def handleNchnls(self, event): x = int(self.tx_chnls.GetValue()) if x != self.nchnls: status, path = self.parent.checkForMixedSound() if not status: self.tx_chnls.SetValue(str(self.nchnls)) return if "Mixed sound" in self.sndPath: self.sndPath = path self.nchnls = x self.meter.setNumSliders(self.nchnls) self.shutdownServer() self.bootServer() def getSamplingRate(self): return self.samplingRate def setSamplingRate(self, x): SR = {44100: 0, 48000: 1, 96000: 2} if x != self.samplingRate: self.samplingRate = x self.pop_sr.SetSelection(SR[self.samplingRate]) self.shutdownServer() self.bootServer() def handleSamplingRate(self, event): SR = {0: 44100, 1: 48000, 2: 96000} x = SR[event.GetInt()] if x != self.samplingRate: status, path = self.parent.checkForMixedSound() if not status: SR = {44100: 0, 48000: 1, 96000: 2} self.pop_sr.SetSelection(SR[self.samplingRate]) return if "Mixed sound" in self.sndPath: self.sndPath = path self.samplingRate = x self.shutdownServer() self.bootServer() def getFileFormat(self): return self.fileformat def setFileFormat(self, x): self.fileformat = x self.pop_fileformat.SetSelection(self.fileformat) def handleFileFormat(self, event): self.fileformat = event.GetInt() def getSampleType(self): return self.sampletype def setSampleType(self, x): self.sampletype = x self.pop_sampletype.SetSelection(self.sampletype) def handleSampleType(self, event): self.sampletype = event.GetInt() def bootServer(self): self.parent.sg_audio.boot(self.parent.audioDriver, self.nchnls, self.samplingRate, self.midiInterface) self.tog_audio.Enable() if self.sndPath != "" and self.tempState == None: self.loadSound(self.sndPath) if self.tempState != None: self.parent.setState(self.tempState) self.tempState = None def shutdownServer(self): self.tempState = self.parent.getState() self.parent.sg_audio.shutdown() self.tog_audio.Disable() self.surface.Refresh() def handleAudio(self, event): if event.GetInt() == 1: if self.sndPath == "": self.parent.log('*** No sound loaded! ***') self.tog_audio.SetValue(0) self.parent.menu.Check(7, False) else: self.tx_chnls.Disable() self.tx_chnls.SetBackgroundColour("#EEEEEE") self.pop_sr.Disable() self.parent.enableDrivers(False) self.parent.midiSettings.popupInterface.Disable() self.tog_audio.SetLabel('Stop') self.tog_audio.SetValue(1) self.parent.menu.Check(7, True) for t in self.surface.getAllTrajectories(): t.initCounter() self.parent.sg_audio.start() else: self.tx_chnls.Enable() self.tx_chnls.SetBackgroundColour("#FFFFFF") self.pop_sr.Enable() self.parent.enableDrivers(True) self.parent.midiSettings.popupInterface.Enable() self.tog_audio.SetLabel('Start') self.tog_audio.SetValue(0) self.parent.menu.Check(7, False) self.tog_record.SetValue(0) self.tog_record.SetLabel('Start Rec') self.parent.sg_audio.stop() def handleOutput(self, event): key = event.GetKeyCode() if key == wx.WXK_TAB or key == wx.WXK_RETURN: self.surface.SetFocus() event.Skip() def setRecordFolder(self, str): self.tx_rec_folder.SetValue(str) def setRecordFilename(self, str): self.tx_output.SetValue(str) def handleRecord(self, event): if event.GetInt() == 1: folder = self.tx_rec_folder.GetValue() if folder.startswith("~"): folder = folder.replace("~", os.path.expanduser("~"), 1) if os.path.isdir(folder): filename = os.path.join(folder, self.tx_output.GetValue()) else: filename = os.path.join(os.path.expanduser('~'), "Desktop", self.tx_output.GetValue()) self.parent.sg_audio.recStart(filename, self.fileformat, self.sampletype) self.tog_record.SetLabel('Stop Rec') else: self.tog_record.SetLabel('Start Rec') self.parent.sg_audio.recStop() def chooseRecFolder(self, evt): dlg = wx.DirDialog(self, message="Choose a folder to save Soundgrain's output sounds...", defaultPath=os.path.expanduser("~")) if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() self.tx_rec_folder.SetValue(ensureNFD(path)) dlg.Destroy() self.but_folder.SetValue(0) def logSndInfo(self): self.parent.log(self.sndInfoStr)