#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk

from sugar.activity import activity

path = "."
path2 = "/home/olpc/Activities/FMSynth.activity/"
path3 = "/home/olpc/Activities/FMSynth.activity"

from Csound import *
from CsoundServer import *
import sys
from keyboard import *
import gobject

from knob import Knob
from slider import VSlider, HSlider
from waveformselector import WaveformSelector
from display import Display

gobject.threads_init()

class FMSynthActivity(activity.Activity):
	orchestra = """
nchnls = 2

;standard:
;gisine ftgen 0, 0, 4096, 10, 1, 0.5, 0.25, 0.125
gisine ftgen 0, 0, 4096, 10, 1
;sawtooth:
gisaw ftgen 0, 0, 4096, 7, 0, 0, 1, 4096, -1, 0, 0
;square:
gisquare ftgen 0, 0, 4096, 7, 0, 0, 1, 2048, 1, 0, -1, 128, -1, 0, 0

gisine2 ftgen 0, 0, 4096, 10, 1
gisquare2 ftgen 0, 0, 4096, 7, 0, 4, 1, 2042, 1, 4, -1, 2042, -1, 4, 0

gkamp init 1
gkamp chnexport "Amp", 1, 3, i(gkamp), .001, 1

giIndexAttack init 0.01
giIndexAttack chnexport "IndexAttack", 1, 0, giIndexAttack, 0, 1

giIndexDecay init 0.5
giIndexDecay chnexport "IndexDecay", 1, 0, giIndexDecay, 0, 1

giIndexSustain init 1.0
giIndexSustain chnexport "IndexSustain", 1, 0,giIndexSustain, 0, 1

giIndexRelease init 0.25
giIndexRelease chnexport "IndexRelease", 1, 0, giIndexRelease, 0, 1

giAmpAttack init 0.1
giAmpAttack chnexport "AmpAttack", 1, 0, giAmpAttack, 0, 1

giAmpDecay init 0.5
giAmpDecay chnexport "AmpDecay", 1, 0, giAmpDecay, 0, 1

giAmpSustain init 1.0
giAmpSustain chnexport "AmpSustain", 1, 0,giAmpSustain, 0, 1

giAmpRelease init 0.25
giAmpRelease chnexport "AmpRelease", 1, 0, giAmpRelease, 0, 1

giFilterAttack init 0.01
giFilterAttack chnexport "FilterAttack", 1, 0, giFilterAttack, 0, 1

giFilterDecay init 0.25
giFilterDecay chnexport "FilterDecay", 1, 0, giFilterDecay, 0, 1

giFilterSustain init 1.0
giFilterSustain chnexport "FilterSustain", 1, 0, giFilterSustain, 0, 1

giFilterRelease init 0.01
giFilterRelease chnexport "FilterRelease", 1, 0, giFilterRelease, 0, 1

giIndex init 1
giIndex chnexport "ModulationIndex", 1, 0, giIndex, 0, 12

gkmod init 1
gkmod chnexport "Pitch", 1, 0, i(gkmod), 0, 12

;1=sin, 2=square 3=saw
gkCarrierWave init 1
gkCarrierWave chnexport "CarrierWave", 1, 0, i(gkCarrierWave), 0, 12

gkLFOWave init 1
gkLFOWave chnexport "LFOWave", 1, 0, i(gkLFOWave), 0, 12

gkLFOAmp   init 0
gkLFOAmp chnexport "LFOAmp", 1, 0, i(gkLFOAmp), 0, 2

gkLFOControl   init 1
gkLFOControl chnexport "LFOControl", 1, 0, i(gkLFOControl), 0, 2

gkLFOFreq   init 1
gkLFOFreq chnexport "LFOFreq", 1, 0, i(gkLFOFreq), 0, 2

gkFilterFreq   init 2400
gkFilterFreq chnexport "FilterFreq", 1, 3, i(gkFilterFreq), 500, 2400

gkFilterRes   init 1
gkFilterRes chnexport "FilterRes", 1, 0, i(gkFilterRes), 1, 100;1, 6

instr 1
kpb         init 0

kFreq   cpsmidib
iVel ampmidi 10000

kLFOAmp midictrl    10
kLFOFreq midictrl    11

; scale the value from 0 to 1
kLFOAmp = kLFOAmp / 127


kModPitch  = gkmod
kAmp     = gkamp * 10000
iIndex = giIndex
kLFOAmp = gkLFOAmp
kLFOFreq = gkLFOFreq
iIndexAttack = giIndexAttack
iIndexDecay = giIndexDecay
iIndexSustain = giIndexSustain
iIndexRelease = giIndexRelease
iAmpAttack = giAmpAttack
iAmpDecay = giAmpDecay
iAmpSustain = giAmpSustain
iAmpRelease = giAmpRelease
iFilterAttack = giFilterAttack
iFilterDecay = giFilterDecay
iFilterSustain = giFilterSustain
iFilterRelease = giFilterRelease
kFilterFreq = gkFilterFreq
kFilterRes = gkFilterRes

kCarrierWave = gkCarrierWave
kLFOWave = gkLFOWave



aLFOSine	oscil kAmp * kLFOAmp, kLFOFreq, gisine
aLFOSquare	oscil kAmp * kLFOAmp, kLFOFreq, gisquare2
aLFOSaw		oscil kAmp * kLFOAmp, kLFOFreq, gisaw

aLFO		oscil kAmp * kLFOAmp, kLFOFreq, gisine

kLFOControl = gkLFOControl

aOsc		oscil iVel, kFreq, gisine
aLFOAmp		oscil iVel, kFreq, gisine
aLFOMod		oscil iVel, kFreq, gisine


if (kLFOWave == 1) kgoto LFOSine
if (kLFOWave == 2) kgoto LFOSquare
goto LFOSaw

LFOSine:
aLFO = aLFOSine
goto carrier

LFOSquare:
aLFO = aLFOSquare
goto carrier

LFOSaw:
aLFO = aLFOSaw
goto carrier

carrier:
if (kLFOControl == 1) kgoto Amp
	goto Mod

Amp:
	aLFOAmp = aLFO + kAmp
	aLFOMod = kModPitch
	goto CONTINUE
Mod:
	aLFOAmp = kAmp
	aLFOMod = kModPitch + (50 * aLFO / kAmp)
	goto CONTINUE


CONTINUE:
;	printk .1, kAmp

aAmpEnv		madsr  iAmpAttack, iAmpDecay, iAmpSustain, iAmpRelease, 0, iAmpRelease
kIndexEnv	madsr  iIndexAttack, iIndexDecay, iIndexSustain, iIndexRelease, 0, iIndexRelease
aFilterEnv	madsr  iFilterAttack, iFilterDecay, iFilterSustain, iFilterRelease, 0, iFilterRelease


aSine		foscil aLFOAmp, kFreq, 1, aLFOMod, iIndex*kIndexEnv, gisine;1
aSquare		foscil aLFOAmp, kFreq, 1, aLFOMod, iIndex*kIndexEnv, gisquare
aSaw		foscil aLFOAmp, kFreq, 1, aLFOMod, iIndex*kIndexEnv, gisaw




if (kCarrierWave == 1) kgoto CarrierSine
if (kCarrierWave == 2) kgoto CarrierSquare
goto CarrierSaw

CarrierSine:
aOsc = aSine
goto play
CarrierSquare:
aOsc = aSquare
goto play
CarrierSaw:
aOsc = aSaw
goto play


play:
aOsc = (aOsc * aAmpEnv)

acompressor	compress aOsc, aOsc, -24, 48, 80, 2, .01, .5, .05
abalance	balance acompressor, acompressor
afilter		rezzy abalance, kFilterFreq, kFilterRes
afilter = (afilter * aFilterEnv)
aclip		clip afilter, 2, 30000
aout = aclip
	outs aout, aout
	endin
"""

	score = """
f0 1200
"""

	
	def init_csoundpath(self,csoundpath):
        	self.csoundpath = csoundpath
	
	def main(self):
		toplevel_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.init(toplevel_window)
		gtk.main()
	
	def __init__(self, handle):
		
		activity.Activity.__init__(self, handle)
		
		self.server = None
		self.csound = None
		
		self.set_title("FM Synth")
		self.set_flags(gtk.CAN_FOCUS)
		self.grab_focus()
		
#	self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK)
		self.connect("destroy", self.destroy)
		self.connect("key-press-event", self.onKeyPress)
		self.connect("key-release-event", self.onKeyRelease)
		
		#self.window.set_size_request(800, 600)
		self.set_resizable(False)
		self.bg_color_gtk = gtk.gdk.Color(65535,55555,65535)
		self.bg_color_cairo = [1., 55555./65535., 1.]
		self.modify_bg(gtk.STATE_NORMAL, self.bg_color_gtk)
		self.initializeParameters()
		
		self.setupCsound()
	        self.setupWidgets()

		self.show()
		
		
		

	def destroy(self, data=None):
		print "destroy signal"
		
		if self.server != None:
			if self.server.didLaunch():
				if self.csound != None:
					self.csound.shutdownServer()
		
		activity.Activity.destroy(self)
		

	def initializeParameters(self):
		self.pitch = 1.0

		self.duration = 4
		self.minDuration = 1
		self.maxDuration = 20
		self.wave = 1
		self.amp = 1.0
		self.ModulatorIndex = 1.0
		self.minAmp = 0.0
		self.maxAmp = 1.0
		
		self.index_attack = 0.01
		self.index_decay = 0.5
		self.index_sustain = 1.0
		self.index_release = 0.25
		
		self.amp_attack = 0.1
		self.amp_decay = 0.5
		self.amp_sustain = 1.0
		self.amp_release = 0.25
		
		self.filter_attack = 0.01
		self.filter_decay = 0.25
		self.filter_sustain = 1.0
		self.filter_release = 0.01



	def onKeyPress(self, widget, event):
		key = gtk.gdk.keyval_name(event.keyval)
		for i in range(0, len(qwerty_map)):
			if key == qwerty_map[i]:
				self.keys.playNote(i)
				break
			
	
	def onKeyRelease(self, widget, event):
		key = gtk.gdk.keyval_name(event.keyval)
		for i in range(0, len(qwerty_map)):
			if key == qwerty_map[i]:
				self.keys.stopNote(i)
		
				break	

	def setupCsound(self):
		instanceName = sys.argv[0] # just use name of script
		if len(sys.argv) > 1:
			address = sys.argv[1]
		else:
			address = 'localhost'
 		
		#self.server = CsoundServer(path3, 'csoundserver')
		self.server = CsoundServer(activity.get_bundle_path(), 'csoundserver')
		#self.server.launch()
		
		self.server.setMessageCallback(self.serverMessages)


		fd = self.server.launch(msgs=1)

	        if fd == None:
			print "Sever failed to launch"
		else:
			#gobject.io_add_watch(fd.fileno(), gobject.IO_IN, 
			#	self.serverMessages, fd) 
			print "Server launched successfully"
		
		self.csound = Csound("FMSynth")#, "localhost")
		self.csound.setMessageCallback(self.csoundMessages)
		self.csound.setupOrchestraAsString(self.orchestra)
		#self.csound.setupScoreAsString(self.score)
		self.csound.setupRealtimeMIDI()
		self.csound.initialize()
		self.csound.perform()
		
		if self.csound.isConnected:
			print "Csound successfully connected"
		else:
			print "Csound failed to connect"		
		


	def setupWidgets(self):
		toolbox = activity.ActivityToolbox(self)
		self.set_toolbox(toolbox)	
		toolbox.show()
		
		
		#for widget in self.window.get_children():
		#	self.window.remove(widget)

		self.layout = gtk.Fixed()

		self.display = Display(colors.black, colors.blue3, colors.blue, 
			300, 30, 2)
		self.display.show()
		self.layout.put(self.display, 500, 10)
		
		#Set up Modulation widgets
		
		self.modulation_label = gtk.Label("M O D U L A T I O N")
		self.modulation_label.show()
		self.layout.put(self.modulation_label, 30, 150)
		
		#Custom slider widget that controls the pitch of the modulator
		#Syntax: HSlider("background_img_name", "indictaor_img_name", minimum_value=0, maximum_value=100, current_value=0)
		self.pitch_slider = HSlider(path2+"img/hslider_bg.png", 
			path2+"img/hslider_nub.png", 0, 100, int(self.pitch*10), 
			"Mod Pitch")
		self.pitch_slider.setValueCallback(self.changePitch)	#register callback for this file to handle a changed value
		self.pitch_slider.setEnterCallback(self.updateDisplay)
		self.pitch_slider.setLeaveCallback(self.clearDisplay)
		self.pitch_slider.show()
		self.layout.put(self.pitch_slider, 25, 290)
		
		self.pitch_label = gtk.Label("Pitch")
		self.pitch_label.show()
		self.layout.put(self.pitch_label, 120, 292)
		self.modulation_index_label = gtk.Label("Index")
		self.modulation_index_label.show()
		self.layout.put(self.modulation_index_label, 135, 170)
		#Custom slider widget that controls the modulation index
		#Syntax is identical to HSlider
		
		self.index_envelope_label = gtk.Label("Envelope")
		self.index_envelope_label.show()
		self.layout.put(self.index_envelope_label, 370, 170)
		
		self.modulation_index_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.ModulatorIndex*10), "Mod Index")
		self.modulation_index_slider.setValueCallback(self.changeModulationIndex)
		self.modulation_index_slider.setEnterCallback(self.updateDisplay)
		self.modulation_index_slider.setLeaveCallback(self.clearDisplay)
		self.modulation_index_slider.show()
		self.modulation_index_frame = gtk.Frame()
		self.modulation_index_frame.show()
		self.modulation_index_frame.add(self.modulation_index_slider)
		self.layout.put(self.modulation_index_frame, 140, 190)
	
		self.index_envelope_label = gtk.Label("Envelope")
		self.index_envelope_label.show()
		self.layout.put(self.index_envelope_label, 45, 170)
		
		self.index_attack_slider = VSlider(path2+"img/vslider_bg.png", 
		path2+"img/vslider_nub.png", 0, 100, int(self.index_attack*100), 
		"Ndx Attack")
		self.index_attack_slider.setValueCallback(self.changeIndexAttack)	#register callback
		self.index_attack_slider.setEnterCallback(self.updateDisplay)
		self.index_attack_slider.setLeaveCallback(self.clearDisplay)
		self.index_attack_slider.show()
		self.layout.put(self.index_attack_slider, 25, 190)
		
		self.index_decay_slider = VSlider(path2+"img/vslider_bg.png", 
		path2+"img/vslider_nub.png", 0, 100, int(self.index_decay*100), 
		"Ndx Decay")
		self.index_decay_slider.setValueCallback(self.changeIndexDecay)	#register callback
		self.index_decay_slider.setEnterCallback(self.updateDisplay)
		self.index_decay_slider.setLeaveCallback(self.clearDisplay)
		self.index_decay_slider.show()
		self.layout.put(self.index_decay_slider, 50, 190)
		
		self.index_sustain_slider = VSlider(path2+"img/vslider_bg.png", 
		path2+"img/vslider_nub.png", 0, 100, int(self.index_sustain*100), 
		"Ndx Sustain")
		self.index_sustain_slider.setValueCallback(self.changeIndexSustain)	#register callback
		self.index_sustain_slider.setEnterCallback(self.updateDisplay)
		self.index_sustain_slider.setLeaveCallback(self.clearDisplay)
		self.index_sustain_slider.show()
		self.layout.put(self.index_sustain_slider, 75, 190)
		
		self.index_release_slider = VSlider(path2+"img/vslider_bg.png", 
		path2+"img/vslider_nub.png", 0, 100, int(self.index_release*100), 
		"Ndx Release")
		self.index_release_slider.setValueCallback(self.changeIndexRelease)	#register callback
		self.index_release_slider.setEnterCallback(self.updateDisplay)
		self.index_release_slider.setLeaveCallback(self.clearDisplay)
		self.index_release_slider.show()
		self.layout.put(self.index_release_slider, 100, 190)
		
		
		
		#Set up Carrier widgets
		
		self.carrier_label = gtk.Label("C A R R I E R")
		self.carrier_label.show()
		self.layout.put(self.carrier_label, 45, 25)
		
		self.waveform_label = gtk.Label("Oscillator")
		self.waveform_label.show()
		self.layout.put(self.waveform_label, 55, 45)
		
		self.carrier_wave = WaveformSelector(colors.blue3, colors.blue, colors.aqua3, colors.white, 50, 50, self.wave, "Carrier Wave")
		self.carrier_wave.setValueCallback(self.changeCarrierWave)
		self.carrier_wave.setEnterCallback(self.updateDisplay)
		self.carrier_wave.setLeaveCallback(self.clearDisplay)
		self.layout.put(self.carrier_wave, 60, 65)
		self.carrier_wave.show()
		
		self.lfo_label = gtk.Label("L F O")
		self.lfo_label.show()
		self.layout.put(self.lfo_label, 335, 25)
			
		self.lfo_wave_label = gtk.Label("Shape")
		self.lfo_wave_label.show()
		self.layout.put(self.lfo_wave_label, 252, 45)
		
		self.lfo_wave = WaveformSelector(colors.blue3, colors.blue, colors.aqua3, colors.white, 50, 50, self.wave, "LFO Shape")
		self.lfo_wave.setValueCallback(self.changeLFOWave)
		self.lfo_wave.setEnterCallback(self.updateDisplay)
		self.lfo_wave.setLeaveCallback(self.clearDisplay)
		self.layout.put(self.lfo_wave, 250, 65)
		self.lfo_wave.show()
		
		self.lfo_depth = Knob(path2+"img/knob.png", self.bg_color_cairo, 
			0, 100, 0, 5, "LFO Depth")
		self.lfo_depth.setValueCallback(self.changeLFODepth)
		self.lfo_depth.setEnterCallback(self.updateDisplay)
		self.lfo_depth.setLeaveCallback(self.clearDisplay)
		self.lfo_depth.show()
		self.lfo_depth_label = gtk.Label("Depth")
		self.lfo_depth_label.show()
		self.lfo_depth_frame = gtk.Frame()
		self.lfo_depth_frame.add(self.lfo_depth)
		self.lfo_depth_frame.show()
		self.layout.put(self.lfo_depth_label, 330, 45)
		self.layout.put(self.lfo_depth_frame, 325, 65)

		self.lfo_freq = Knob(path2+"img/knob.png", self.bg_color_cairo, 
			1, 20, 1, 1, "LFO Freq")
		self.lfo_freq.setValueCallback(self.changeLFOFreq)
		self.lfo_freq.setEnterCallback(self.updateDisplay)
		self.lfo_freq.setLeaveCallback(self.clearDisplay)
		self.lfo_freq.show()
		self.lfo_freq_frame = gtk.Frame()
		self.lfo_freq_frame.add(self.lfo_freq)
		self.lfo_freq_frame.show()
		self.lfo_freq_label = gtk.Label("Frequency")
		self.lfo_freq_label.show()
		self.layout.put(self.lfo_freq_label, 395, 45)
		self.layout.put(self.lfo_freq_frame, 400, 65)
		
		#Filter
		
		self.filter_label = gtk.Label("F I L T E R")
		self.filter_label.show()
		self.layout.put(self.filter_label, 320, 150)
		
		self.filter_freq = Knob(path2+"img/knob.png", 
			self.bg_color_cairo, 0, 100, 100, 5, "Filter Freq")
		self.filter_freq.setValueCallback(self.changeFilterFreq)
		self.filter_freq.setEnterCallback(self.updateDisplay)
		self.filter_freq.setLeaveCallback(self.clearDisplay)
		self.filter_freq.show()
		self.filter_freq_frame = gtk.Frame()
		self.filter_freq_frame.add(self.filter_freq)
		self.filter_freq_frame.show()
		self.filter_freq_label = gtk.Label("Frequency")
		self.filter_freq_label.show()
		self.layout.put(self.filter_freq_label, 245, 170)
		self.layout.put(self.filter_freq_frame, 250, 190)
		
		self.filter_res = Knob(path2+"img/knob.png", self.bg_color_cairo, 
			1, 100, 1, 5, "Filter Res")
		self.filter_res.setValueCallback(self.changeFilterRes)
		self.filter_res.setEnterCallback(self.updateDisplay)
		self.filter_res.setLeaveCallback(self.clearDisplay)
		self.filter_res.show()
		self.filter_res_frame = gtk.Frame()
		self.filter_res_frame.add(self.filter_res)
		self.filter_res_frame.show()
		self.filter_res_label = gtk.Label("Resonance")
		self.filter_res_label.show()
		self.layout.put(self.filter_res_label, 240, 250)
		self.layout.put(self.filter_res_frame, 250, 270)
		
		self.filter_envelope_label = gtk.Label("Envelope")
		self.filter_envelope_label.show()
		self.layout.put(self.filter_envelope_label, 370, 170)
		
		self.filter_attack_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.filter_attack*100), "Flt Attack")
		self.filter_attack_slider.setValueCallback(self.changeFilterAttack)	#register callback
		self.filter_attack_slider.setEnterCallback(self.updateDisplay)
		self.filter_attack_slider.setLeaveCallback(self.clearDisplay)
		self.filter_attack_slider.show()
		self.layout.put(self.filter_attack_slider, 350, 190)
		
		self.filter_decay_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.filter_decay*100), "Flt Decay")
		self.filter_decay_slider.setValueCallback(self.changeFilterDecay)	#register callback
		self.filter_decay_slider.setEnterCallback(self.updateDisplay)
		self.filter_decay_slider.setLeaveCallback(self.clearDisplay)
		self.filter_decay_slider.show()
		self.layout.put(self.filter_decay_slider, 375, 190)
		
		self.filter_sustain_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.filter_sustain*100), "Flt Sustain")
		self.filter_sustain_slider.setValueCallback(self.changeFilterSustain)	#register callback
		self.filter_sustain_slider.setEnterCallback(self.updateDisplay)
		self.filter_sustain_slider.setLeaveCallback(self.clearDisplay)
		self.filter_sustain_slider.show()
		self.layout.put(self.filter_sustain_slider, 400, 190)
		
		self.filter_release_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.filter_release*100), "Flt Release")
		self.filter_release_slider.setValueCallback(self.changeFilterRelease)	#register callback
		self.filter_release_slider.setEnterCallback(self.updateDisplay)
		self.filter_release_slider.setLeaveCallback(self.clearDisplay)
		self.filter_release_slider.show()
		self.layout.put(self.filter_release_slider, 425, 190)
		
		#Set up graphical keyboard
		
		#Syntax: Keyboard(width=200, height=100, number_of_notes=24, "type"),
		#where "type" is either "midi" or "pch"
		self.keys = Keyboard(300, 150, 29, "midi", colors.blue2)
		self.keys.setNoteOnCallback(self.NoteOn)		#now register callbacks for this file to handle
		self.keys.setNoteOffCallback(self.NoteOff)		#note on and note off signals
		self.keys.show()
		self.layout.put(self.keys, 200, 400)
		
		#Set up amplitude widgets
		
		self.amplitude_label = gtk.Label("A M P L I T U D E")
		self.amplitude_label.show()
		self.layout.put(self.amplitude_label, 650, 150)
		
		self.amp_envelope_label = gtk.Label("Envelope")
		self.amp_envelope_label.show()
		self.layout.put(self.amp_envelope_label, 620, 170)
		
		self.amp_attack_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.amp_attack*100), "Amp Attack")
		self.amp_attack_slider.setValueCallback(self.changeAmpAttack)	#register callback
		self.amp_attack_slider.setEnterCallback(self.updateDisplay)
		self.amp_attack_slider.setLeaveCallback(self.clearDisplay)
		self.amp_attack_slider.show()
		self.layout.put(self.amp_attack_slider, 600, 190)
		
		self.amp_decay_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.amp_decay*100), "Amp Decay")
		self.amp_decay_slider.setValueCallback(self.changeAmpDecay)	#register callback
		self.amp_decay_slider.setEnterCallback(self.updateDisplay)
		self.amp_decay_slider.setLeaveCallback(self.clearDisplay)
		self.amp_decay_slider.show()
		self.layout.put(self.amp_decay_slider, 625, 190)
		
		self.amp_sustain_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.amp_sustain*100), "Amp Sustain")
		self.amp_sustain_slider.setValueCallback(self.changeAmpSustain)	#register callback
		self.amp_sustain_slider.setEnterCallback(self.updateDisplay)
		self.amp_sustain_slider.setLeaveCallback(self.clearDisplay)
		self.amp_sustain_slider.show()
		self.layout.put(self.amp_sustain_slider, 650, 190)
		
		self.amp_release_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, 
			int(self.amp_release*100), "Amp Release")
		self.amp_release_slider.setValueCallback(self.changeAmpRelease)	#register callback
		self.amp_release_slider.setEnterCallback(self.updateDisplay)
		self.amp_release_slider.setLeaveCallback(self.clearDisplay)
		self.amp_release_slider.show()
		self.layout.put(self.amp_release_slider, 675, 190)
		
		self.amplitude_slider = VSlider(path2+"img/vslider_bg.png", 
			path2+"img/vslider_nub.png", 0, 100, int(self.amp*100), 
			"Volume")
		self.amplitude_slider.setValueCallback(self.changeAmplitude)	#register callback
		self.amplitude_slider.setEnterCallback(self.updateDisplay)
		self.amplitude_slider.setLeaveCallback(self.clearDisplay)
		self.amplitude_slider.show()
		self.amplitude_label = gtk.Label("Volume")
		self.amplitude_label.show()
		self.layout.put(self.amplitude_label, 735, 170)
		self.layout.put(self.amplitude_slider, 750, 190)
		
		#self.clear_canvas(self.layout)
		#self.toolbar_init(self.layout)
		#self.add(self.layout)
		#self.set_canvas(self.layout)
		self.set_canvas(self.layout)
		self.layout.show()

	def updateDisplay(self, chars, value):
		#print chars, value
		self.display.setCharacters(chars, value)
	
	def clearDisplay(self):
		chars = ""
		#print chars, -1
		self.display.setCharacters(chars, -1)	
	
	#Define callback methods, as referenced in setupWidgets
	
	def changeCarrierWave(self, value):
		self.csound.writeValueToChannel("CarrierWave", value)
		#!!print "Waveform: ", value
	
	def changeLFOWave(self, value):
		self.csound.writeValueToChannel("LFOWave", value)
		#!!print "Waveform: ", value
	
	def changePitch(self, value):
		value = 1.*(10)/100*value
		self.csound.writeValueToChannel("Pitch", value)
		#!!print "Pitch:", value

	def changeModulationIndex(self, value):
		value = 1.*(10)/100*value
		self.csound.writeValueToChannel("ModulationIndex", value)
		#!!print "Mod Index:", value
	def changeIndexAttack(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("IndexAttack", value)
		#!!print "Attack:", value
		
	def changeIndexDecay(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("IndexDecay", value)
		#!!print "Decay:", value
	
	def changeIndexSustain(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("IndexSustain", value)
		#!!print "Sustain:", value
	
	def changeIndexRelease(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("IndexRelease", value)
		#!!print "Release:", value

	def changeAmplitude(self, value):
		value = 1.*(self.maxAmp - self.minAmp)/100*value + self.minAmp
		self.csound.writeValueToChannel("Amp", value)
		#!!print "Volume:", value

	def changeAmpAttack(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("AmpAttack", value)
		#!!print "Attack:", value
		
	def changeAmpDecay(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("AmpDecay", value)
		#!!print "Decay:", value
	
	def changeAmpSustain(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("AmpSustain", value)
		#!!print "Sustain:", value
	
	def changeAmpRelease(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("AmpRelease", value)
		#!!print "Release:", value
	
	def changeLFODepth(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("LFOAmp", value)
		#!!print "LFO Depth:", value

	def changeLFOFreq(self, value):
		self.csound.writeValueToChannel("LFOFreq", value)
		#!!print "LFO Freq:", value
	
	def changeFilterFreq(self, value):
		value = (value+1)*24
		self.csound.writeValueToChannel("FilterFreq", value)
		#!!print "Filter Freq:", value
		
	def changeFilterRes(self, value):
		value = (value+1)
		self.csound.writeValueToChannel("FilterRes", value)
		#!!print "Filter Res:", value
	
	def changeFilterAttack(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("FilterAttack", value)
		#!!print "Attack:", value
		
	def changeFilterDecay(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("FilterDecay", value)
		#!!print "Decay:", value
	
	def changeFilterSustain(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("FilterSustain", value)
		#!!print "Sustain:", value
	
	def changeFilterRelease(self, value):
		value = 1./100*(value+1)
		self.csound.writeValueToChannel("FilterRelease", value)
		#!!print "Release:", value
	
	def NoteOn(self, pitch, user_data = None):
		self.csound.playMIDINoteOn(pitch,127)

	def NoteOff(self, pitch, user_data = None):
		self.csound.playMIDINoteOff(pitch)
	


	def csoundMessages(self, message):
		#pass
		message.display("csound: ")
	
	def serverMessages(self, line, data1=None, data2=None):
		print "Server: ", line, data1, data2
	        # return True to keep processing
	        return True


if __name__ == "__main__":
	fmsynth = FMSynthActivity()
	fmsynth.csoundpath = "."
	fmsynth.main()
