#!/usr/bin/python
import pygst
pygst.require("0.10")
import gst
import pygtk
import gtk
import gtk.glade
import time

class Instrument:
	def __init__(self, project, filename, insnum):

		self.project = project

		##### BEGIN PIPELINE CONSTRUCTION ##########		

		gst.debug("Adding an instrument gnlcomposition")
		self.comp = gst.element_factory_make("gnlcomposition", "mycomposition" + str(insnum))
		self.comp.connect("pad-added", self.project.OnPad, self)

		self.compconvert = gst.element_factory_make("audioconvert", "compaudioconvertconvert" + str(insnum))
		self.project.pipeline.add(self.compconvert)

		gst.debug("Adding a gnlfilesource")
		self.audio = gst.element_factory_make("gnlfilesource", "gnlfilesource" + str(insnum))
		self.audio.set_property("location", filename)
		self.audio.set_property("start", long(0))
		self.audio.set_property("duration", long(60) * gst.SECOND)
		self.audio.set_property("priority", 2)
		self.comp.add(self.audio)

		self.op = gst.element_factory_make("gnloperation", "gnloperation" + str(insnum))
		self.op.set_property("start", long(10) * gst.SECOND)
		self.op.set_property("duration", long(5) * gst.SECOND)
		self.op.set_property("priority", 2)

		effect1 = self.CreateEffectsBin("ladspa-PhaserII", insnum)
		self.op.add(effect1)
		
		self.comp.add(self.op)

		self.op2 = gst.element_factory_make("gnloperation", "gnloperation2" + str(insnum))
		self.op2.set_property("start", long(5) * gst.SECOND)
		self.op2.set_property("duration", long(25) * gst.SECOND)
		self.op2.set_property("priority", 1)

		effect2 = self.CreateEffectsBin("ladspa-lowpass-iir", insnum)
		self.op2.add(effect2)
		
		self.comp.add(self.op2)

		self.project.pipeline.add(self.comp)

		self.volume = gst.element_factory_make("volume", "volume" + str(insnum))
		self.project.pipeline.add(self.volume)

		self.level = gst.element_factory_make("level", "level" + str(insnum))
		self.project.pipeline.add(self.level)
		gst.debug("Adding an instrument audioconvert")
		self.convert = gst.element_factory_make("audioconvert", "convert" + str(insnum))
		self.project.pipeline.add(self.convert)
		self.resample = gst.element_factory_make("audioresample", "resample" + str(insnum))
		self.project.pipeline.add(self.resample)

		self.compconvert.link(self.volume)
		self.volume.link(self.level)
		self.level.link(self.convert)
		self.convert.link(self.resample)
		self.resample.link(self.project.masteradder)

		##### END PIPELINE CONSTRUCTION ##########		

	def CreateEffectsBin(self, effectel, insnum):
		effectsbin = gst.element_factory_make("bin", "effectsbin" + str(insnum))
		
		effect = gst.element_factory_make(effectel, "effect" + str(insnum))
		effectsbin.add(effect)

		effectlac = gst.element_factory_make("audioconvert", "efflac" + str(insnum))
		effectsbin.add(effectlac)
		
		effectrac = gst.element_factory_make("audioconvert", "effrac" + str(insnum))
		effectsbin.add(effectrac)
		
		effectlac.link(effect)
		effect.link(effectrac)

		for pad in effectlac.pads():
			if pad.get_direction() == gst.PAD_SINK:
				print "got sink pad"
				effectsbinsink = gst.GhostPad("sink", pad)

		for pad in effectrac.pads():
			if pad.get_direction() == gst.PAD_SRC:
				print "got src pad"
				effectsbinsrc = gst.GhostPad("src", pad)

		effectsbin.add_pad(effectsbinsink)
		effectsbin.add_pad(effectsbinsrc)
	
		return effectsbin

class Project:
	def __init__(self):
		print "Running class"

		instruments = []

		self.pipeline = gst.Pipeline("mixer")

		self.bus = self.pipeline.get_bus()
		self.bus.add_signal_watch()
		self.bus.connect("message::error", self.BusMessage)

		gst.debug("Adding master adder")
		self.masteradder = gst.element_factory_make("adder", "masteradder")
		self.pipeline.add(self.masteradder)

		gst.debug("Adding alsasink")

		self.out = gst.element_factory_make("alsasink", "out")
		self.out.set_property("device", "default")
		self.pipeline.add(self.out)

		gst.debug("Linking masteradder to alsasink")

		# need to restrict the format on adder's output
		caps = gst.caps_from_string ("audio/x-raw-int,"
		    "rate=44100,channels=2,endianness=1234,width=16,depth=16,signed=(boolean)true")

		self.masteradder.link(self.out, caps)

		# change the file names to something on your computer
		
		self.ins1 = Instrument(self, "/home/jono/media/audioforjokosher/jonobacon-thelake.ogg", 1)

	def OnPad(self, comp, pad, instrument):
		print "pad added!"
		gst.debug("Pad added")
		convpad = instrument.compconvert.get_compatible_pad(pad, pad.get_caps())
		
		t1 = time.time()
		pad.link(convpad)
		t2 = time.time()
		print "Time taken to link:", t2 - t1
	def Play(self):
		self.pipeline.set_state(gst.STATE_PLAYING)
		print self.pipeline.get_state(0)

	def Stop(self):
		self.pipeline.set_state(gst.STATE_READY)
		print self.pipeline.get_state(0)

	def BusMessage(self, bus, message):
		st = message.structure
		error, debug = message.parse_error()
		print "!!!! bus message error: " + str(error)
		print "!!!! bus message debug: " + str(debug)

		
class Main:
	def __init__(self):
		self.project = Project()

		self.wTree = gtk.glade.XML("buggui.glade", "mainwindow")
		
		signals = {
			"on_play_clicked" : self.OnPlay,
			"on_stop_clicked" : self.OnStop,
			"on_quit_clicked" : self.OnQuit,
		}

		self.wTree.signal_autoconnect(signals)

		self.window = self.wTree.get_widget("mainwindow")
		self.window.show_all()

	def OnPlay(self, widget):
		print "play"
		self.project.Play()

	def OnStop(self, widget):
		print "stop"
		self.project.Stop()

	def OnQuit(self, widget):
		gtk.main_quit()

start=Main()
gtk.main()
