from sugar.activity import activity
import logging

from CsoundServer import *
from CsoundEventSequencer import *

import random
import sys, os
import gtk

import gobject

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

gisin	ftgen	1, 0, 4096, 10, 1

    instr	10

iPitchHigh	= 	8.17579891564 * exp(0.0577622650 * (p4+36))
iPitchLow	= 	8.17579891564 * exp(0.0577622650 * p4)

kPitch    expon    iPitchHigh, p3 * 0.5, iPitchLow

aAmp      line    ampdbfs(-12), p3, 0

a1         oscil	aAmp, kPitch, gisin

    outs	a1, a1
    endin
    """


    def destroy(self, data=None):
        if self.server.didLaunch():
            self.sequencer.shutdownServer()
            
        activity.Activity.destroy(self)

    def launchServer(self):
        self.server = CsoundServer(activity.get_bundle_path(), 'csoundserver')
        fd = self.server.launch()        
        if fd != None:
            gobject.io_add_watch(fd.fileno(), gobject.IO_IN, self.serverMessages, fd)                 
            print "Successfully Launched Server"
        else:
            print "Problem launching..."

    def __init__(self, handle):        
        activity.Activity.__init__(self, handle)
        
        self.launchServer()
        
        self.set_title('Step Activity')
        self.initializeParameters()
                
        # Creates the Toolbox. It contains the Activity Toolbar, which is the
        # bar that appears on every Sugar window and contains essential
        # functionalities, such as the 'Collaborate' and 'Close' buttons.
        toolbox = activity.ActivityToolbox(self)
        self.set_toolbox(toolbox)
        toolbox.show()
        
        
        widgets = self.setupWidgets()
        widgets.show_all()


        # create the sequencer
        self.sequencer = CsoundEventSequencer("StepSequencer", self.orchestra)        
        # connect to at least one server
        connection = self.sequencer.addConnection("localhost")
        connection.registerTime(self.timeUpdate, 0.1) # 10x per sec
            
        # NOW ITS OKAY TO ISSUE COMMANDS TO THE SEQUENCER (we're connected)
        
        # add a sequencer track
        self.sequencer.requestNewTrack()

        # we want to loop around
        self.sequencer.setLoopEnabled(True)
        self.sequencer.setLoopPoints(0, 4) # start, duration
                                        
        # Set the button to be our canvas. The canvas is the main section of
        # every Sugar Window. It fills all the area below the toolbox.
        self.set_canvas(widgets)
        

    def tempoSliderChanged(self, widget, data=None):                
        self.sequencer.setTempo(widget.get_value())
        
    def toggle(self, widget, data=None):        
        start = data * 0.25

        if widget.get_active():
            start = data * 0.25
            duration = 0.25
            notenum = 48
            self.sequencer.track(0).requestNewEvent(start, duration, notenum)
        
        else:
            event = self.sequencer.track(0).timeIntersectsEvent(start)
            if event != None:
                self.sequencer.track(0).requestRemoveEvent(event)                
                                                            

    def timeUpdate(self, message):
        
        self.currentTime.set_label(str(message.argument(0)))
        
    def initializeParameters(self):
        """
        Initialize performance parameters
        """
        self.tempo = 120
        self.maxTempo = 240
        self.minTempo = 30

    def setupWidgets(self):
        """
        Construct the gtk interface - layout of buttons and sliders
        """        
        self.layout = gtk.Layout()
        self.layout.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#C0C0C0"))
        
        self.tempo = 120
        self.maxTempo = 240
        self.minTempo = 30
                
        # value, lower, upper, step_increment, page_increment, page_size
        self.tempoSlider = gtk.HScale(gtk.Adjustment(self.tempo, self.minTempo, self.maxTempo, 1.0, 1.0, 1.0))
        self.tempoSlider.connect("value_changed", self.tempoSliderChanged, self.tempoSlider)
        self.tempoSlider.set_update_policy(gtk.UPDATE_CONTINUOUS)
        self.tempoSlider.set_size_request(400, 30)
        self.tempoSlider.show()
        
        tempoLabel = gtk.Label('tempo')
        patternLabel = gtk.Label('pattern')
        self.currentTime = gtk.Label('0.0')


        playButton = gtk.Button("play")
        playButton.set_size_request(100, 40)
        playButton.connect("clicked", self.play)

        pauseButton = gtk.Button("pause")
        pauseButton.set_size_request(100, 40)
        pauseButton.connect("clicked", self.pause)

        stopButton = gtk.Button("stop")
        stopButton.set_size_request(100, 40)
        stopButton.connect("clicked", self.stop)

        clearButton = gtk.Button("clear")
        clearButton.set_size_request(100, 40)
        clearButton.connect("clicked", self.clear)


        self.layout.put(playButton, 25, 50)        
        self.layout.put(pauseButton, 125, 50)        
        self.layout.put(stopButton, 225, 50)        
        self.layout.put(clearButton, 325, 50)        

                
        self.layout.put(tempoLabel, 25, 150)        
        self.layout.put(self.tempoSlider, 25, 185)
        self.layout.put(patternLabel, 25, 250)
        
        self.layout.put(gtk.Label('current time'), 250, 250)        
        self.layout.put(self.currentTime, 425, 250)        


        
        self.buttons = []
        
        for i in range(16):
            button = gtk.ToggleButton(" ")
            button.connect("clicked", self.toggle, i)
            button.show()
            self.layout.put(button, 35 * i + 25, 285)
            
            # keep track of the button
            self.buttons.append(button)

        return self.layout

    def play(self, widget, data = None):
        self.sequencer.play()
    def pause(self, widget, data = None):
        self.sequencer.pause()
    def stop(self, widget, data = None):
        self.sequencer.stop()
    def clear(self, widget, data = None):
        for button in self.buttons:
            button.set_active(False)
            
        self.sequencer.clearTrack(0)

    def serverMessages(self, source, condition, userData = None):
        print userData.readline(),
        return True

    def csoundMessages(self, message):
        message.display("Csound")
