diff --git a/src/config.py b/src/config.py index 892ce9a0..4afdce52 100644 --- a/src/config.py +++ b/src/config.py @@ -16,10 +16,10 @@ from ct.path import * from ct.call import * # Helpful variables used by the application -# vars["$user"] is the users home directory -# vars["$ocarina"] is the directory ocarina uses to store all its files -# vars["$lockfile"] is the lockfile used by the application -# vars["$writeenable"] controls enables printing from ct.call.write() +# vars.USER is the users home directory +# vars.OCARINA is the directory ocarina uses to store all its files +# vars.LOCKFILE is the lockfile used by the application +# vars.WRITEENABLE controls enables printing from ct.call.write() ################################################################################ ################################################################################ @@ -35,29 +35,35 @@ from ct.call import * # Set this variable to force verbosity to always be at the same value. # Calling ocarina with the -v option will have no effect. A higher value will # print more output -#vars["$verbose"] = 0 +#vars.VERBOSE = 0 # Setting this variable to change the prompt that is presented to the user # by the built in command line. This variable is only used in ocarina-core -#vars["$prompt"] = ">>>" +#vars.PROMPT = ">>>" # This variable controls if ocarina begins playback as soon as a song is loaded # The default value is True -vars["$playonload"] = False +vars.PLAYONLOAD = False # This variable controls the gstreamer volume at startup. Values must be # between 0.0 and 1.0, values less than 0.0 will be changed to 0.0 and values # greater than 1.0 will be changed to 1.0 -#vars["$volume"] = 1.0 +#vars.VOLUME = 1.0 # This variable controls how much the volume changes when calling # volup() or voldown() -#vars["$volumeincr"] = 0.05 +#vars.VOLUMEINCR = 0.05 # This variable controls the port that ocarina listens on for requests. Other # ocarina instances will connect to this port to forward a song to load. # Setting this variable to 0 will cause ocarina to use a random port. -#vars["$port"] = 12345 +#vars.PORT = 12345 + +# These next variables are the initial text shown in the artist, album, title +# labels. They will be overwritten when a song is loaded. +#vars.ARTIST = "" +#vars.ALBUM = "" +#vars.TITLE = "" @@ -80,7 +86,7 @@ readline.parse_and_bind("tab:complete") # Configure readline history. # This file is written after every command entered, but you can comment out # these lines to ignore the file -history = join(ocarina.vars["$ocarina"],"history") +history = join(vars.OCARINA,"history") if exists( history ): readline.read_history_file(history) @@ -104,14 +110,10 @@ readline.set_history_length(50) # Ocarina uses an xml-based system to build up the GUI. This allows you to # create your own custom gui. -#vars["$theme"] = "themes/simple.xml" -vars["$theme"] = "themes/classic.xml" - -# These next variables are the initial text shown in the artist, album, title -# labels. They will be overwritten when a song begins playback. -#vars["$artist"] = "" -#vars["$album"] = "" -#vars["$title"] = "" +#vars.THEME = "themes/simple.xml" +#vars.THEME = "themes/classic.xml" +#vars.THEME = "themes/ocarina3.xml" +vars.THEME = "themes/simple2.xml" # Initial text for library / playlist / queue filtering -#vars["$filterText"] = "" \ No newline at end of file +#vars.FILTERTEXT = "" \ No newline at end of file diff --git a/src/core/cli.py b/src/core/cli.py deleted file mode 100644 index 8cf4e75a..00000000 --- a/src/core/cli.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/python - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -__author__="bjschuma" -__date__ ="$Mar 13, 2010 9:08:56 PM$" - -import ocarina - -from ct.path import * -from ct.call import * -import readline - -global history -history = join(ocarina.vars["$ocarina"],"history") - - -def loop(): - while True: - try: - state = ocarina.vars["$writeenable"] - ocarina.vars["$writeenable"] = True - exec raw_input(ocarina.vars["$prompt"] + " ") - ocarina.vars["$writeenable"] = state - - global history - readline.write_history_file(history) - - # Catch this so that we can use ctrl-d to exit - except EOFError: - print "" - exit() - except Exception,e: - print e - - -#ocarina.events.invite("ocarina-start",loop) \ No newline at end of file diff --git a/src/core/coredefaults.py b/src/core/coredefaults.py deleted file mode 100644 index fee0eedd..00000000 --- a/src/core/coredefaults.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/python - -__author__="bjschuma" -__date__ ="$Mar 15, 2010 9:53:46 PM$" - -import ocarina -import os -from ct import path -from ct import opts -from ocarina import vars - - -# Set the default values of ocarina variables -vars["$user"] = path.expand("~") -vars["$ocarina"] = path.join(vars["$user"],".ocarina3") -vars["$lockfile"] = path.join(vars["$ocarina"],"lock") -vars["$writeenable"] = True - -vars["$verbose"] = 0 -vars["$prompt"] = ">>>" -vars["$playonload"] = True -vars["$playing"] = False -vars["$volume"] = 1.0 -vars["$volumeincr"] = 0.05 -vars["$port"] = 0 - - -opts.parse() -path.mkdir(vars["$ocarina"]) - - -# Set verbose value -if opts.opts.has("v") == True: - vars["$verbose"] += opts.opts["v"] -if opts.opts.has("verbose") == True: - vars["$verbose"] += opts.opts["verbose"] - -#import gstreamer diff --git a/src/core/ct/__init__.py b/src/core/ct/__init__.py index 24d9c675..0a5a2396 100644 --- a/src/core/ct/__init__.py +++ b/src/core/ct/__init__.py @@ -2,4 +2,4 @@ __author__="bjschuma" __date__ ="$Mar 13, 2010 4:20:16 PM$" -__all__ = ["call", "dict", "opts", "path", "plugin", "slist", "tcp", "times"] \ No newline at end of file +__all__ = ["call", "opts", "path", "tags", "tcp", "times"] \ No newline at end of file diff --git a/src/core/ct/call.py b/src/core/ct/call.py index 3bfebb53..72c594a6 100644 --- a/src/core/ct/call.py +++ b/src/core/ct/call.py @@ -7,27 +7,28 @@ __author__="bjschuma" __date__ ="$Mar 30, 2010 11:24:43 PM$" -import ocarina -import sys +from ocarina import events +from ocarina import vars from ct import times from ct import path def exit(): '''Safely exit ocarina''' - path.rm(ocarina.vars["$lockfile"]) + path.rm(vars.LOCKFILE) import gstreamer - ocarina.events.start("ocarina-close") + import sys + events.start(events.OCARINA_QUIT) sys.exit(0) def about(): - print "Ocarina Version 3.0" - print "Written by Bryan Schumaker (bjschuma@umich.edu)" + write("Ocarina Version 3.0") + write("Written by Bryan Schumaker (bjschuma@umich.edu)") -def write(s,verbose): - if (ocarina.vars["$writeenable"]==True) and (ocarina.vars["$verbose"]>=verbose): +def write(s,verbose=0): + if vars.VERBOSE >= verbose: print str(s) @@ -35,22 +36,24 @@ def load(path): '''Load the song located at path''' import gstreamer gstreamer.load(path) + from ct import tags + tags.get(path) def seek(prcnt): ''' Seek to prcnt% of the song. If 0 < prcnt < 1, then we will seek to (prcnt * 100)% of song's duration. If prcnt < 100, then we will seek to prcnt% of the song's duration.''' - import gstreamer - good = gstreamer.seek(prcnt) + from gstreamer import position + good = position.seek(prcnt) if good == -1: write("There was an error seeking to: "+str(prcnt)) def progress(): '''Return the fraction of the song that we have already played''' - import gstreamer - progress = gstreamer.getProgress() + from gstreamer import position + progress = position.getProgress() write(progress) return progress @@ -59,8 +62,8 @@ def duration(): '''Return the total duration of the song. If message printing is enabled, then we will also print out string representing the duration in hh:mm:ss form''' - import gstreamer - duration = gstreamer.duration() + from gstreamer import position + duration = position.duration() write(times.ms2str(duration)) return duration @@ -69,28 +72,50 @@ def time(): '''Returns how far into the song gstreamer currently is. If message printing is enabled, then we will also print out a string representing the duration in hh:mm:ss form''' - import gstreamer - time = gstreamer.currentpos() - message.write(times.ms2str(time)) + from gstreamer import position + time = position.currentpos() + write(times.ms2str(time)) return time def gsstate(): '''Returns the current gstreamer state''' - import gstreamer - state = gstreamer.getstate() - message.write(state) + from gstreamer import playback + state = playback.getstate() + write(state) return state +def playing(disp=True): + '''Returns true if ocarina is currently playing''' + from gstreamer import playback + import gst + state = playback.getstate() == gst.STATE_PLAYING + if disp==True: + if state == True: + write("Ocarina is playing") + else: + write("Ocarina is not playing") + return state + + +def tags(disp=True): + '''Returns (title, artist, album) for the current track''' + if disp == True: + print vars.TITLE + print "by",vars.ARTIST + print "from",vars.ALBUM + return (vars.TITLE, vars.ARTIST, vars.ALBUM) + + def play(): '''Begin playback of the loaded song''' - ocarina.events.start("ocarina-play") + events.start(events.OCARINA_PLAY) def pause(): '''Pause playback of the current song''' - ocarina.events.start("ocarina-pause") + events.start(events.OCARINA_PAUSE) def stop(): @@ -101,14 +126,14 @@ def stop(): def volup(): '''Increase the volume''' - import gstreamer - gstreamer.volup() + from gstreamer import volume + volume.volup() def voldown(): '''Decrease the volume''' - import gstreamer - gstreamer.voldown() + from gstreamer import volume + volume.voldown() def pyfile(file): diff --git a/src/core/ct/dict.py b/src/core/ct/dict.py deleted file mode 100644 index c8a9a53e..00000000 --- a/src/core/ct/dict.py +++ /dev/null @@ -1,17 +0,0 @@ -#! /usr/bin/python - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -__author__="bjschuma" -__date__ ="$Feb 24, 2010 8:59:47 PM$" - - - -class Dict(dict): - def __init__(self): - dict.__init__(self) - - - def has(self,key): - return (key in self.keys()) diff --git a/src/core/ct/plugin.py b/src/core/ct/plugin.py deleted file mode 100644 index 5a59dece..00000000 --- a/src/core/ct/plugin.py +++ /dev/null @@ -1,49 +0,0 @@ -#! /usr/bin/python - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -__author__="bjschuma" -__date__ ="$Mar 14, 2010 2:58:02 PM$" - -import inspect -import os -from ct.message import write - - -class Plugin: - def __init__(self): - self.enabled = True - self.help = dict() - self.usage = dict() - self.minarg = 0 - - - def open(self): - pass - - - def close(self): - pass - - - def run(self,args): - return None - - - def start(self,args=None): - if len(args) < self.minarg: - return - try: - return self.run(args) - - # Find out information about the error - except Exception,e: - trace = inspect.trace() - frame = trace[len(trace)-1] - - filename = frame[1] - lineno = str(frame[2]) - - filename = filename.rsplit(os.sep,1)[1] - write(filename+" ("+lineno+"): "+str(e)) diff --git a/src/core/ct/slist.py b/src/core/ct/slist.py deleted file mode 100644 index 101190e9..00000000 --- a/src/core/ct/slist.py +++ /dev/null @@ -1,22 +0,0 @@ - -__author__="bjschuma" -__date__ ="$Feb 22, 2010 10:52:13 PM$" - - -# This is a sorted list (as long as items are inserted with add() ) -class Slist(list): - def __init__(self): - list.__init__(self) - - - def add(self, item, priority): - self += [(priority,item)] - self.sort() - - - def remove(self, item): - for tuple in self: - if tuple[1] == item: - list.remove(self,tuple) - break - diff --git a/src/core/ct/tags.py b/src/core/ct/tags.py new file mode 100644 index 00000000..c04f8dc9 --- /dev/null +++ b/src/core/ct/tags.py @@ -0,0 +1,19 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 12, 2010 10:34:18 AM$" + + +import tagpy +from ocarina import vars + + +def get(path): + file = tagpy.FileRef(path) + tags = file.tag() + vars.ARTIST = tags.artist + vars.ALBUM = tags.album + vars.TITLE = tags.title diff --git a/src/core/ct/times.py b/src/core/ct/times.py index 6a7c186d..a4bb3682 100644 --- a/src/core/ct/times.py +++ b/src/core/ct/times.py @@ -39,3 +39,40 @@ def ms2str(ms): # Convert ms to s time = int(ms) / 1000000000 return ftime(time) + + +def hms2sec(hms): + if hms == None: + return 0 + split = hms.split(":")[::-1] + + sec = int( split[0] ) + if len(split) >= 2: + sec += int( split[1] ) * 60 + if len(split) == 3: + sec += int( split[2] ) * 60 * 60 + + return sec + + +def sec2text(s): + def fmt(time, field): + if time <= 0: + return "" + if time > 1: + field += "s" + return str(time) + " " + field + " " + + sec = s + day = sec / 86500 + sec -= day*86500 + + hour = sec / 3600 + sec -= hour*3600 + + min = sec / 60 + sec -= min*60 + + st = fmt(day,"day") + fmt(hour,"hour") + fmt(min,"minute") + fmt(sec,"second") + return st + diff --git a/src/core/event.py b/src/core/event.py index 208403ca..162ad901 100644 --- a/src/core/event.py +++ b/src/core/event.py @@ -7,39 +7,43 @@ __author__="bjschuma" __date__ ="$Feb 24, 2010 9:13:41 PM$" -from ct.dict import Dict -from ct.slist import Slist -from ct.call import * - # Maintain the list of guests -class GuestList(Slist): - def __init__(self,name): - Slist.__init__(self) - self.name = name +class GuestList(list): + def __init__(self): + list.__init__(self) self.active = False + def add(self, item, priority): + self += [(priority, item)] + self.sort() -class Event(Dict): +class Event(dict): def __init__(self): - Dict.__init__(self) + dict.__init__(self) + self.nextEvent = 0 + self.create("OCARINA_START") + self.create("OCARINA_QUIT") + self.create("OCARINA_PLAY") + self.create("OCARINA_PAUSE") - def type(self,guest): - return type(guest).__name__ + def create(self,name): + var = "self." + name.upper() + exec var + " = " + str(self.nextEvent) + self.nextEvent += 1 + exec "self["+var+"] = GuestList()" + + + def has(self,key): + return (key in self.keys()) # Add a "guest" (function or script) to this event def invite(self, name, guest, priority=None): - type = self.type(guest) if priority==None: - if type=='str' or type=='unicode': - priority = 200 - else: priority = 100 - if self.has(name) == False: - self[name] = GuestList(name) self[name].add(guest, priority) @@ -60,17 +64,13 @@ class Event(Dict): self[name].active = True for priority,guest in self[name]: - if self[name].active == True: - if self.type(guest)=='unicode' or self.type(guest)=='str': - pyfile(guest) - elif args==None: + if self[name].active == False: + break + elif self[name].active == True: + if args==None: guest() else: guest(args) self.stop(name) - - - - diff --git a/src/core/gstreamer.py b/src/core/gstreamer.py deleted file mode 100644 index 5dfc00e7..00000000 --- a/src/core/gstreamer.py +++ /dev/null @@ -1,267 +0,0 @@ -#! /usr/bin/python - -__author__ = "bjschuma" -__date__ = "$Feb 5, 2010 7:53:19 PM$" - -from ct import path -from ct.call import write -from ct.opts import args -import gst -import ocarina - -global player -global time - -player = gst.element_factory_make("playbin2", "player") -time = gst.Format(gst.FORMAT_TIME) -bus = player.get_bus() - - - -def getstate(): - global player - state = player.get_state()[1] - write("Gstreamer state: "+str(state), 3) - return player.get_state()[1] - - -def play(): - global player - player.set_state(gst.STATE_PLAYING) - if getstate() != gst.STATE_PLAYING: - ocarina.events.stop("ocarina-play") - else: - ocarina.vars["$playing"] = True - - -def pause(): - global player - player.set_state(gst.STATE_PAUSED) - if getstate() != gst.STATE_PAUSED: - ocarina.events.stop("ocarina-pause") - else: - ocarina.vars["$playing"] = False - - -def load(song): - song = path.expand(song) - if path.exists(song) == False: - write("Path does not exist: " + song) - return - - curstate = getstate() - pause() - write("Loading file: " + song, 1) - global player - player.set_state(gst.STATE_NULL) - player.set_property("uri", "file://" + song) - if ocarina.vars["$playonload"]==True or curstate==gst.STATE_PLAYING: - play() - else: - pause() - #player.set_state(gst.STATE_PAUSED) - - -def uninit(): - global player - player.set_state(gst.STATE_NULL) - - - -def onMessage(bus, message): - #print message.type - if message.type == gst.MESSAGE_TAG: - taglist = message.parse_tag() - for tag in taglist.keys(): - write("Found tag: ("+tag+", "+str(taglist[tag])+")",1) - if tag == "title": - ocarina.vars["$title"] = taglist[tag] - elif tag == "artist": - ocarina.vars["$artist"]= taglist[tag] - elif tag == "album": - ocarina.vars["$album"] = taglist[tag] - ocarina.events.start("tags-changed") - - -def duration(): - global player - global time - state = getstate() - if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): - return 0 - total = player.query_duration(time)[0] - return total - - -def currentpos(): - global player - global time - state = getstate() - if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): - return 0 - position = player.query_position(time)[0] - return position - - -def getProgress(): - global player - global time - state = getstate() - if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): - return 0 - total = duration() - current = currentpos() - fraction = float(current) / float(total) - if fraction < 0.0: - return 0.0 - elif fraction > 1.0: - return 1.0 - return fraction - - -# Seek to the desired percent of the song. -# Fraction is True if prcnt is already a fraction -def seek(prcnt): - global player - global time - if prcnt < 0: - prcnt = 0 - elif prcnt > 100: - prcnt = 1 - elif prcnt > 1: - prcnt = float(prcnt) / 100.0 - newTime = duration() * prcnt - player.seek_simple(time,gst.SEEK_FLAG_FLUSH,newTime) - return 0 - - -def setvol(volume): - global player - if volume > 1.0: - volume = 1.0 - elif volume < 0.0: - volume = 0.0 - player.set_property("volume",volume) - ocarina.vars["$volume"] = volume - - -def volup(): - volume = ocarina.vars["$volume"] - volume += ocarina.vars["$volumeincr"] - setvol(volume) - - -def voldown(): - volume = ocarina.vars["$volume"] - volume -= ocarina.vars["$volumeincr"] - setvol(volume) - - -bus.add_signal_watch() -bus.connect("message", onMessage) -ocarina.events.invite("ocarina-close", uninit) -ocarina.events.invite("ocarina-play", play,50) -ocarina.events.invite("ocarina-pause", pause,50) -setvol(ocarina.vars["$volume"]) - -# -#def setvol(value): -# global pipeline -# curvol = float( settings.get("volume") ) -# -# vol = pipeline.get_by_name("vol") -# if value == "up": -# value = curvol + 0.05 -# elif value == "down": -# value = curvol - 0.05 -# else: -# # Prevent converting strings -# try: -# value = float(value) -# except: -# return -# -# if value > 1.0: -# value = 1.0 -# if value < 0.0: -# value = 0.0 -# settings.set("volume",value) -# vol.set_property("volume",value ) -# -# -#def getProgress(tuple=False): -# global pipeline -# global time -# -# # Don't bother to go on if the pipeline isn't playing -# if not pipeline.get_state()[1] == gst.STATE_PLAYING: -# return -1 -# -# position = pipeline.query_position(time)[0] -# total = pipeline.query_duration(time)[0] -# if tuple==False: -# return float(position) / float(total) -# else: -# return (position,total) -# -# -## Draw the progress bar on the command line -#def drawProgress(): -# p = getProgress() -# if p == -1: -# return -# win = settings.get("maxyx") -# max = int(win[1] * p) -# if max > win[1]: -# max = win[1] -# if max == 0: -# cline.message.disp(" "*(win[1]-1) ,win[0]-1) -# else: -# cline.message.disp("="*max, win[0]-1) -# -# -## A callback when there are messages on the bus -#def onMessage(bus,message): -# if message.type == gst.MESSAGE_EOS: -# manager.run("next") -# -# -## Manually check the bus for messages -#def checkBus(): -# global bus -# if bus.peek() == None: -# return -# onMessage(bus,bus.pop()) -# -# -# -#def init(): -# # Register signals -# signal.register("play",play) -# signal.register("pause",pause) -# signal.register("cliloop",drawProgress) -# signal.register("cliloop",checkBus,90) -# -# # Check for settings values -# if settings.has("args") == True: -# input = settings.get("args") -# if not input == []: -# join = ' ' -# path = join.join(input) -# load(path) -# else: -# if settings.has("curtrk")==True: -# track = settings.get("curtrk") -# if track > 0: -# manager.run("next",[track,False]) -# if settings.has("volume") == False: -# settings.set("volume",1.0) -# setvol(settings.get("volume")) -# -# -#def close(): -# global pipeline -# global bin -# pause() -# pipeline.set_state(gst.STATE_NULL) -# bin.set_state(gst.STATE_NULL) diff --git a/src/core/gstreamer/__init__.py b/src/core/gstreamer/__init__.py new file mode 100644 index 00000000..25648de9 --- /dev/null +++ b/src/core/gstreamer/__init__.py @@ -0,0 +1,50 @@ + +__author__="bjschuma" +__date__ ="$May 11, 2010 10:31:27 PM$" + + +__all__ = ["playback", "position", "volume"] + + +import gst + +from ocarina import vars +from ocarina import events +from ct import path +from ct import call + +global player +global time + +player = gst.element_factory_make("playbin2", "player") +time = gst.Format(gst.FORMAT_TIME) + + + +def load(song): + song = path.expand(song) + if path.exists(song) == False: + call.write("Path does not exist: " + song) + return + + playing = call.playing(False) + if playing == True: + call.pause() + + call.write("Loading file: " + song, 1) + + global player + player.set_state(gst.STATE_NULL) + player.set_property("uri", "file://" + song) + + if (vars.PLAYONLOAD == True) or (playing==True): + call.play() + + +def init(): + from gstreamer import playback + from gstreamer import volume + from gstreamer import position + + +init() \ No newline at end of file diff --git a/src/core/gstreamer/playback.py b/src/core/gstreamer/playback.py new file mode 100644 index 00000000..331278c5 --- /dev/null +++ b/src/core/gstreamer/playback.py @@ -0,0 +1,34 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 11, 2010 10:55:54 PM$" + +import gst +from ocarina import events +from gstreamer import player +from ct import call + + +def getstate(): + state = player.get_state()[1] + call.write("Gstreamer state: "+str(state), 3) + return player.get_state()[1] + + +def play(): + player.set_state(gst.STATE_PLAYING) + if getstate() != gst.STATE_PLAYING: + events.stop(events.OCARINA_PLAY) + + +def pause(): + player.set_state(gst.STATE_PAUSED) + if getstate() != gst.STATE_PAUSED: + events.stop(events.OCARINA_PAUSE) + + +events.invite(events.OCARINA_PLAY, play, 50) +events.invite(events.OCARINA_PAUSE, pause, 50) diff --git a/src/core/gstreamer/position.py b/src/core/gstreamer/position.py new file mode 100644 index 00000000..c0d7081c --- /dev/null +++ b/src/core/gstreamer/position.py @@ -0,0 +1,57 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 11, 2010 11:50:23 PM$" + + +import gst +from gstreamer import player +from gstreamer import time +from gstreamer.playback import getstate + + +def duration(): + state = getstate() + if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): + return 0 + total = player.query_duration(time)[0] + return total + + +def currentpos(): + state = getstate() + if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): + return 0 + position = player.query_position(time)[0] + return position + + +def getProgress(): + state = getstate() + if (state!=gst.STATE_PLAYING) and (state!=gst.STATE_PAUSED): + return 0 + total = duration() + current = currentpos() + fraction = float(current) / float(total) + if fraction < 0.0: + return 0.0 + elif fraction > 1.0: + return 1.0 + return fraction + + +# Seek to the desired percent of the song. +# Fraction is True if prcnt is already a fraction +def seek(prcnt): + if prcnt < 0: + prcnt = 0 + elif prcnt > 100: + prcnt = 1 + elif prcnt > 1: + prcnt = float(prcnt) / 100.0 + newTime = duration() * prcnt + player.seek_simple(time,gst.SEEK_FLAG_FLUSH,newTime) + return 0 diff --git a/src/core/gstreamer/volume.py b/src/core/gstreamer/volume.py new file mode 100644 index 00000000..21a8c10e --- /dev/null +++ b/src/core/gstreamer/volume.py @@ -0,0 +1,35 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 11, 2010 10:32:12 PM$" + + +from gstreamer import player +from ocarina import vars + + +def setvol(volume): + if volume > 1.0: + volume = 1.0 + elif volume < 0.0: + volume = 0.0 + player.set_property("volume",volume) + vars.VOLUME = volume + + +def volup(): + volume = vars.VOLUME + volume += vars.VOLUMEINCR + setvol(volume) + + +def voldown(): + volume = vars.VOLUME + volume -= vars.VOLUMEINCR + setvol(volume) + + +setvol(vars.VOLUME) diff --git a/src/core/ocarina-core.py b/src/core/ocarina-core.py index 05576b2a..1b7af207 100644 --- a/src/core/ocarina-core.py +++ b/src/core/ocarina-core.py @@ -3,23 +3,31 @@ __author__="bjschuma" __date__ ="$Mar 13, 2010 4:19:31 PM$" + import ocarina -import coredefaults -import cli +print "Welcome to Ocarina 3.0 (core)" + +ocarina.config() + + +ocarina.events.start(ocarina.events.OCARINA_START) + + from ct.call import * -from ct import tcp +from ct.path import * +import readline +# ocarina-core main loop +while True: + try: + exec raw_input(ocarina.vars.PROMPT + " ") + readline.write_history_file(ocarina.vars.HISTORYFILE) -def main(): - # Potentially the first thing printed - write("Welcome to Ocarina (core)", 1) - - ocarina.events.start("ocarina-start") - code = ocarina.config() - if code == 0: - cli.loop() - - -if __name__ == "__main__":main() + # Catch this so that we can use ctrl-d to exit + except EOFError: + print "" + exit() + except Exception,e: + print 1,e diff --git a/src/core/ocarina.py b/src/core/ocarina.py index 926bbc04..03c02033 100644 --- a/src/core/ocarina.py +++ b/src/core/ocarina.py @@ -3,36 +3,45 @@ __author__="bjschuma" __date__ ="$Mar 13, 2010 4:19:39 PM$" - -from ct.dict import Dict -from ct import path +import variables import event - global vars global events - -vars = Dict() +vars = variables.Vars() events = event.Event() +from ct import path +from ct import opts + +path.mkdir(vars.OCARINA) +opts.parse() +# Set verbose value +if opts.opts.has("v") == True: + vars.VERBOSE += opts.opts["v"] +if opts.opts.has("verbose") == True: + vars.VERBOSE += opts.opts["verbose"] + + +import gstreamer + + def postConfig(): from ct import tcp global vars - lock = vars["$lockfile"] + lock = vars.LOCKFILE from ct.opts import args # Load a song if we were passed one on load space = ' ' song = space.join(args) - #if exists( song ): - # load(song) # Check if another instance already has the lock if path.exists(lock) == True: # Print a warning message, and tell where the lock file is so the user # can remove it if this message is in error print "Warning: an instance of Ocarina may already be running!" - print "If this is not the case, remove the lock file located at:" + print "If this is not the case, remove the lock file located at:" print lock # Find the port of the other application fin = open(lock) @@ -43,7 +52,7 @@ def postConfig(): tcp.send(port,song) return -1 except: - print "Alert: I could not connect to port",port + print "Warning: I could not connect to port",port print "We will continue as if this is the only Ocarina" # Become a tcp server @@ -67,7 +76,10 @@ def config(): global vars from ct.call import pyfile config = "config.py" - pyfile(path.join(vars["$ocarina"],config)) + pyfile(path.join(vars.OCARINA,config)) pyfile(config) - return postConfig() + if postConfig() != 0: + import sys + sys.exit() + diff --git a/src/core/variables.py b/src/core/variables.py new file mode 100644 index 00000000..4bca1a87 --- /dev/null +++ b/src/core/variables.py @@ -0,0 +1,29 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 10, 2010 5:57:02 PM$" + + +from ct import path + + +class Vars: + def __init__(self): + self.USER = path.expand("~") + self.OCARINA = path.join(self.USER, ".ocarina3") + self.LOCKFILE = path.join(self.OCARINA, "lock") + self.HISTORYFILE = path.join(self.OCARINA, "history") + + self.PLAYONLOAD = True + self.PORT = 0 + self.PROMPT = ">>>" + self.VERBOSE = 0 + self.VOLUME = 1.0 + self.VOLUMEINCR = 0.05 + self.ARTIST = "" + self.ALBUM = "" + self.TITLE = "" + diff --git a/src/extra/db.py b/src/extra/db.py index eb732f8d..f26bf60d 100644 --- a/src/extra/db.py +++ b/src/extra/db.py @@ -162,7 +162,7 @@ def gettrack(trid): select = "track.id,track.name,track.length,artist.name,album.name,track.count" where = "track.artist=artist.id AND track.album=album.id AND track.id="+str(trid) sel = sql.Select(select,"track,artist,album",where) - return sel.execute().fetchone() + return list( sel.execute().fetchone() ) init() \ No newline at end of file diff --git a/src/extra/et/sql.py b/src/extra/et/sql.py index d01d00f7..9740579b 100644 --- a/src/extra/et/sql.py +++ b/src/extra/et/sql.py @@ -14,7 +14,7 @@ import ocarina def getdb(): - return join(ocarina.vars["$ocarina"],"ocarina.db") + return join(ocarina.vars.OCARINA,"ocarina.db") def dbexists(): diff --git a/src/extra/extradefaults.py b/src/extra/extradefaults.py deleted file mode 100644 index a9a60632..00000000 --- a/src/extra/extradefaults.py +++ /dev/null @@ -1,21 +0,0 @@ -#! /usr/bin/python - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -__author__="bjschuma" -__date__ ="$Mar 15, 2010 9:56:53 PM$" - - -from ocarina import vars -import coredefaults -vars["$theme"] = "themes/simple.xml" -#vars["$theme"] = "themes/classic.xml" -vars["$artist"] = "" -vars["$album"] = "" -vars["$title"] = "" -vars["$filterText"] = "" - - -import guibuilder -from oGtk import * \ No newline at end of file diff --git a/src/extra/gtkextras/__init__.py b/src/extra/gtkextras/__init__.py new file mode 100644 index 00000000..bc80b556 --- /dev/null +++ b/src/extra/gtkextras/__init__.py @@ -0,0 +1,5 @@ +__author__="bjschuma" +__date__ ="$May 16, 2010 7:21:27 PM$" + + +__all__ = ["dialog"] \ No newline at end of file diff --git a/src/extra/gtkextras/dialog.py b/src/extra/gtkextras/dialog.py new file mode 100644 index 00000000..27004a34 --- /dev/null +++ b/src/extra/gtkextras/dialog.py @@ -0,0 +1,34 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 7:21:50 PM$" + +import gtk + + +class FileChooser(gtk.FileChooserDialog): + def __init__(self,title,file=None,seldir=False): + buttons = (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK) + action=gtk.FILE_CHOOSER_ACTION_OPEN + gtk.FileChooserDialog.__init__(self,title,None,action=action,buttons=buttons) + + if file != None: + self.select_filename(file) + + if seldir == True: + self.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + + + def choose(self): + response = self.run() + self.hide() + file = "" + #print response + if response == gtk.RESPONSE_OK: + file = self.get_filename() + if response != gtk.RESPONSE_OK: + return None + return file diff --git a/src/extra/gtknodes/__init__.py b/src/extra/gtknodes/__init__.py new file mode 100644 index 00000000..d22c446a --- /dev/null +++ b/src/extra/gtknodes/__init__.py @@ -0,0 +1,46 @@ +__author__="bjschuma" +__date__ ="$May 13, 2010 10:37:20 AM$" + + +__all__ = ["box", "importnode", "menu", "node", "window"] + + +from ct.call import write + + +global parts +parts = dict() + + + +def make(child): + global parts + name = str(child.nodeName).lower() + if (name in parts.keys()) == False: + return None + node = parts[name](child) + if name == "import": + return node.part + return node + + +from gtknodes.box import * +parts["vbox"] = VBox +parts["hbox"] = HBox + + +from gtknodes.importnode import * +parts["import"] = Import + + +from gtknodes.menu import * +parts["menubar"] = bar.MenuBar +parts["menuitem"] = item.MenuItem +parts["menuchangetheme"] = theme.MenuChangeTheme +parts["menureloadtheme"] = theme.MenuReloadTheme +parts["menuselectsong"] = playback.MenuSelectSong + + +from gtknodes.window import * +parts["window"] = Window +parts["scrollwindow"] = ScrolledWindow diff --git a/src/extra/gtknodes/box.py b/src/extra/gtknodes/box.py new file mode 100644 index 00000000..1607dc75 --- /dev/null +++ b/src/extra/gtknodes/box.py @@ -0,0 +1,53 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 13, 2010 11:46:36 AM$" + + +from gtknodes.node import Node +import gtk + + +class BoxNode(Node): + def __init__(self, elm, box): + Node.__init__(self, elm) + self["pack"] = "start" + self["expand"] = "false" + self["fill"] = "false" + self["pad"] = 0 + self.part = box() + self.setattrs() + self.pack() + + + def packval(self,key,node): + if ( key in node.keys() ) == True: + return node[key] + return self[key] + + + def pack(self): + for child in self.children: + pack = self.packval("pack", child) + expand = self.packval("expand", child) == "true" + fill = self.packval("fill", child) == "true" + pad = int( self.packval("pad", child) ) + + if pack == "start": + self.part.pack_start(child.part, expand, fill, pad) + else: + self.part.pack_end(child.part, expand, fill, pad) + + + +class HBox(BoxNode): + def __init__(self,elm): + BoxNode.__init__(self, elm, gtk.HBox) + + +class VBox(BoxNode): + def __init__(self,elm): + BoxNode.__init__(self, elm, gtk.VBox) diff --git a/src/extra/gtknodes/importnode.py b/src/extra/gtknodes/importnode.py new file mode 100644 index 00000000..4c658686 --- /dev/null +++ b/src/extra/gtknodes/importnode.py @@ -0,0 +1,19 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 10:24:55 PM$" + + +from gtknodes.node import Node + + +class Import(Node): + def __init__(self,elm): + Node.__init__(self,elm) + self["show"] = False + self.setattrs() + from gui import buildfile + self.part = buildfile(self["src"]) \ No newline at end of file diff --git a/src/extra/gtknodes/menu/__init__.py b/src/extra/gtknodes/menu/__init__.py new file mode 100644 index 00000000..749252a5 --- /dev/null +++ b/src/extra/gtknodes/menu/__init__.py @@ -0,0 +1,20 @@ +__author__="bjschuma" +__date__ ="$May 16, 2010 7:23:22 PM$" + + +__all__ = ["bar", "item", "playback", "theme"] + + +import gtk +from gtknodes import Node + + +class MenuNode(Node): + def __init__(self, elm, title): + Node.__init__(self,elm) + self.part = gtk.MenuItem(title) + self.setattrs() + self.part.connect("activate", self.onclick) + + def onclick(self, menu): + pass \ No newline at end of file diff --git a/src/extra/gtknodes/menu/__init__.pyc b/src/extra/gtknodes/menu/__init__.pyc new file mode 100644 index 00000000..5dd09b92 Binary files /dev/null and b/src/extra/gtknodes/menu/__init__.pyc differ diff --git a/src/extra/gtknodes/menu/bar.py b/src/extra/gtknodes/menu/bar.py new file mode 100644 index 00000000..7e3afb43 --- /dev/null +++ b/src/extra/gtknodes/menu/bar.py @@ -0,0 +1,23 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 7:25:18 PM$" + +from gtknodes import Node +import gtk + + +class MenuBar(Node): + def __init__(self,elm): + Node.__init__(self,elm) + self.part = gtk.MenuBar() + self.setattrs() + self.makemenu() + + + def makemenu(self): + for child in self.children: + self.part.append(child.part) diff --git a/src/extra/gtknodes/menu/bar.pyc b/src/extra/gtknodes/menu/bar.pyc new file mode 100644 index 00000000..f2e7d26e Binary files /dev/null and b/src/extra/gtknodes/menu/bar.pyc differ diff --git a/src/extra/gtknodes/menu/item.py b/src/extra/gtknodes/menu/item.py new file mode 100644 index 00000000..d489f757 --- /dev/null +++ b/src/extra/gtknodes/menu/item.py @@ -0,0 +1,27 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 7:26:59 PM$" + + +from gtknodes import Node +import gtk + +class MenuItem(Node): + def __init__(self,elm): + Node.__init__(self,elm) + self["name"] = "menu" + self.part = gtk.MenuItem() + self.menu = gtk.Menu() + self.part.set_submenu(self.menu) + self.setattrs() + self.part.set_label(self["name"].title()) + self.makemenu() + + + def makemenu(self): + for child in self.children: + self.menu.append(child.part) diff --git a/src/extra/gtknodes/menu/item.pyc b/src/extra/gtknodes/menu/item.pyc new file mode 100644 index 00000000..375caf00 Binary files /dev/null and b/src/extra/gtknodes/menu/item.pyc differ diff --git a/src/extra/gtknodes/menu/playback.py b/src/extra/gtknodes/menu/playback.py new file mode 100644 index 00000000..81664eef --- /dev/null +++ b/src/extra/gtknodes/menu/playback.py @@ -0,0 +1,25 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 10:08:35 PM$" + + +from gtknodes.menu import MenuNode + + +class MenuSelectSong(MenuNode): + def __init__(self,elm): + MenuNode.__init__(self, elm, "Select a song") + self.file = None + + + def onclick(self, menu): + from gtkextras import dialog + song = dialog.FileChooser("Select a song", self.file).choose() + if song != None: + from ct import call + self.file = song + call.load(song) diff --git a/src/extra/gtknodes/menu/playback.pyc b/src/extra/gtknodes/menu/playback.pyc new file mode 100644 index 00000000..3501b71e Binary files /dev/null and b/src/extra/gtknodes/menu/playback.pyc differ diff --git a/src/extra/gtknodes/menu/theme.py b/src/extra/gtknodes/menu/theme.py new file mode 100644 index 00000000..efb93548 --- /dev/null +++ b/src/extra/gtknodes/menu/theme.py @@ -0,0 +1,32 @@ +#! /usr/bin/python + +__author__="bjschuma" +__date__ ="$May 16, 2010 7:24:02 PM$" + +import gui +from ocarina import vars +from gtknodes.menu import MenuNode + + +class MenuReloadTheme(MenuNode): + def __init__(self,elm): + MenuNode.__init__(self, elm, "Reload Theme") + + + def onclick(self,menu): + gui.build() + + + +class MenuChangeTheme(MenuNode): + def __init__(self,elm): + MenuNode.__init__(self, elm, "Change Theme") + + + def onclick(self,menu): + from gtkextras import dialog + file = dialog.FileChooser("Select a theme file",vars.THEME).choose() + if file != None: + vars.THEME = file + gui.build() + diff --git a/src/extra/gtknodes/menu/theme.pyc b/src/extra/gtknodes/menu/theme.pyc new file mode 100644 index 00000000..1d859970 Binary files /dev/null and b/src/extra/gtknodes/menu/theme.pyc differ diff --git a/src/extra/gtknodes/node.py b/src/extra/gtknodes/node.py new file mode 100644 index 00000000..24ada734 --- /dev/null +++ b/src/extra/gtknodes/node.py @@ -0,0 +1,70 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 16, 2010 10:27:25 PM$" + + +from ct.call import write +from gtknodes import make + + +class Node: + def __init__(self,elm): + write("Creating node: "+elm.nodeName, 2) + self.elm = elm + self.part = None + self.init2() + + def __del__(self): + write("Deleting node: "+self.elm.nodeName, 2) + + def init2(self): + self.name = self.elm.nodeName.lower() + self.attrs = dict() + self.children = self.getchildren() + + def __setitem__(self,key,value): + self.attrs[str(key).lower()] = str(value).lower() + + def __getitem__(self,key): + return self.attrs[str(key).lower()] + + def keys(self): + return self.attrs.keys() + + def show(self): + self.part.show() + + def hide(self): + self.part.hide() + + def setattrs(self): + if ("show" in self.keys()) == False: + self["show"] = "true" + self["viewport"] = "false" + + if self.elm.hasAttributes() == True: + for i in range( self.elm.attributes.length ): + item = self.elm.attributes.item(i) + self[item.name.lower()] = item.nodeValue.lower() + + if self["show"] == "true": + self.part.show() + + def getchildren(self): + if self.elm.hasChildNodes() == False: + return [] + + children = [] + for node in self.elm.childNodes: + if not node.nodeName[0] == "#": + child = self.make(node) + if child != None: + children += [child] + return children + + def make(self,child): + return make(child) \ No newline at end of file diff --git a/src/extra/gtknodes/window.py b/src/extra/gtknodes/window.py new file mode 100644 index 00000000..a469752c --- /dev/null +++ b/src/extra/gtknodes/window.py @@ -0,0 +1,96 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 13, 2010 10:37:48 AM$" + + +from gtknodes import Node +from ct import call +import gtk + + + +class Window(Node): + def __init__(self,elm): + Node.__init__(self,elm) + self.part = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.part.connect("delete_event", self.onquit) + self.wininit() + + + def wininit(self): + self["title"] = "Ocarina 3.0" + self["width"] = "400" + self["height"] = "150" + #self["show"] = "false" + + self.setattrs() + + self.part.set_title(self["title"].title()) + self.part.resize(int(self["width"]), int(self["height"])) + + self.add() + + + def newContent(self,elm): + call.write("Window redrawing content!", 2) + self.elm = elm + self.init2() + self.wininit() + + + def onquit(self,a,b): + call.exit() + + + def add(self): + if len(self.children) == 0: + return + # Add the first child to the window + self.part.add(self.children[0].part) + + + def clear(self): + self.part.remove(self.children[0].part) + + + + +class ScrolledWindow(Node): + def __init__(self,elm): + Node.__init__(self,elm) + self["hscroll"] = "auto" + self["vscroll"] = "auto" + self.part = gtk.ScrolledWindow() + + self.setattrs() + + hscroll = gtk.POLICY_AUTOMATIC + if self["hscroll"] == "none": + hscroll = gtk.POLICY_NONE + elif self["hscroll"] == "always": + hscroll = gtk.POLICY_ALWAYS + + vscroll = gtk.POLICY_AUTOMATIC + if self["vscroll"] == "none": + vscroll = gtk.POLICY_NONE + elif self["vscroll"] == "always": + vscroll = gtk.POLICY_ALWAYS + + self.part.set_policy(hscroll, vscroll) + self.add() + + + def add(self): + if len(self.children) == 0: + return + + # Add the child to the scrolled window + child = self.children[0] + if child["viewport"] == "false": + self.part.add(child.part) + else: + self.part.add_with_viewport(child.part) \ No newline at end of file diff --git a/src/extra/gui.py b/src/extra/gui.py new file mode 100644 index 00000000..d83ff937 --- /dev/null +++ b/src/extra/gui.py @@ -0,0 +1,43 @@ +#! /usr/bin/python + +# To change this template, choose Tools | Templates +# and open the template in the editor. + +__author__="bjschuma" +__date__ ="$May 13, 2010 10:28:46 AM$" + +global window +window = None + +from ocarina import vars +import gtknodes + +import xml +import xml.dom.minidom as xml + + +def load(path): + fin = open(path) + if fin == None: + return None + return xml.parse(fin) + + +def build(): + global window + doc = load(vars.THEME) + if doc == None: + return + + if window != None: + window.clear() + window.newContent(doc.firstChild) + else: + window = gtknodes.make(doc.firstChild) + + +def buildfile(file): + doc = load(file) + if doc == None: + return + return gtknodes.make(doc.firstChild) diff --git a/src/extra/guibuilder.py b/src/extra/guibuilder.py deleted file mode 100644 index 60a16813..00000000 --- a/src/extra/guibuilder.py +++ /dev/null @@ -1,154 +0,0 @@ -#! /usr/bin/python - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -__author__="bjschuma" -__date__ ="$Mar 14, 2010 9:52:10 PM$" - - -import ocarina -from et import xm -from ct.call import write -#from oGtk import * - -import gtk - -global parts -parts = dict() - -global buildFunc -buildFunc = None - -global window -window = None - - -def setPacking(old,newVals): - for field in newVals: - if (field=="expand") or (field=="fill"): - if newVals[field]=="True": - old[field] = True - else: - old[field] = False - elif field=="padding": - old[field] = int(newVals[field]) - - return old - - - -def buildTabs(node,tabs): - global buildFunc - - for child in xm.children(node): - if child.nodeName=="tab": - label = None - content = None - for gchild in xm.children(child): - if gchild.nodeName == "tablabel": - for ggchild in xm.children(gchild): - item = buildFunc(ggchild) - if item != None: - label = item - elif gchild.nodeName == "tabcontent": - for ggchild in xm.children(gchild): - item = buildFunc(ggchild) - if item != None: - content = item - - if content != None: - tabs.append_page(content,label) - attrs = setPacking({"expand":False,"fill":False}, xm.attributes(child) ) - tabs.set_tab_label_packing(content,attrs["expand"],attrs["fill"],gtk.PACK_START) - - -def buildMenu(node,menu): - global buildFunc - for child in xm.children(node): - item = buildFunc(child) - if item!=None: - if node.nodeName == "menu-bar": - menu.append(item) - elif node.nodeName == "menuitem": - menu.addSubMenu(item) - - -def setPacking(old,newVals): - for field in newVals: - if (field=="expand") or (field=="fill"): - if newVals[field]=="True": - old[field] = True - else: - old[field] = False - elif field=="padding": - old[field] = int(newVals[field]) - - return old - - -def fill(node,container): - global buildFunc - pack = True - packing = {"expand":False,"fill":False,"padding":0} - - for child in xm.children(node): - viewport = False - if child.nodeName == "add" or child.nodeName == "add-viewport": - if child.nodeName == "add-viewport": - write("We are adding to "+node.nodeName+" with a viewport",2) - viewport = True - else: - write("We are adding to "+node.nodeName,2) - pack = False - for grandchild in xm.children(child): - item = buildFunc(grandchild) - if item != None: - if viewport == False: - container.add(item) - else: - container.add_with_viewport(item) - - elif child.nodeName == "pack": - packing = setPacking( packing,xm.attributes(child) ) - write("Now using packing: "+str(packing), 2) - - else: - item = buildFunc(child) - if item != None: - if pack == False: - container.add(item) - else: - container.pack_start(item,packing["expand"],packing["fill"],packing["padding"]) - - -def build(node): - global parts - tag = node.nodeName - - if (tag in parts.keys()) == True: - write("Creating part from tag: "+tag,2) - part = parts[tag](xm.attributes(node)) - if (tag=="hbox") or (tag=="vbox") or (tag=="window") or (tag=="scrolled-window"): - fill(node,part) - elif (tag=="menu-bar") or (tag=="menuitem"): - buildMenu(node,part) - elif (tag=="tabs"): - buildTabs(node,part) - return part - - -def init(): - global window - if window != None: - window.hide() - write("Building gui from file: "+ocarina.vars["$theme"],1) - doc = xm.load(ocarina.vars["$theme"]) - window = build( xm.child(doc) ) - ocarina.events.start("ocarina-gui-done") - window.show() - - -buildFunc = build -ocarina.events.invite("ocarina-start",init,50) -ocarina.events.invite("ocarina-stop",gtk.main_quit) \ No newline at end of file diff --git a/src/extra/index.py b/src/extra/index.py index 82284acc..de6571d1 100644 --- a/src/extra/index.py +++ b/src/extra/index.py @@ -23,13 +23,13 @@ alpha = dict() global filePath -filePath = path.join( ocarina.vars["$ocarina"], "index.pickle" ) +filePath = path.join( ocarina.vars.OCARINA, "index.pickle" ) -#if path.exists(filePath) == True: -file = open( filePath ) -p = pickle.Unpickler( file ) -(index,alpha) = p.load() -file.close() +if path.exists(filePath) == True: + file = open( filePath ) + p = pickle.Unpickler( file ) + (index,alpha) = p.load() + file.close() #filePath = "/home/bjschuma/.ocarina3/index.pickle" diff --git a/src/extra/oGtk/__init__.py b/src/extra/oGtk/__init__.py index 984cc009..62c50572 100644 --- a/src/extra/oGtk/__init__.py +++ b/src/extra/oGtk/__init__.py @@ -2,5 +2,5 @@ __author__="bjschuma" __date__ ="$Mar 14, 2010 10:21:40 PM$" -__all__ = ["box", "button", "dialog","entry", "label", "label", "list", "menu", - "progbar", "tabs", "window", "volume"] \ No newline at end of file +__all__ = ["align", "box", "button", "dialog","entry", "label", "label", "list", + "menu", "progbar", "tabs", "window", "volume"] \ No newline at end of file diff --git a/src/extra/oGtk/button.py b/src/extra/oGtk/button.py index 37cb21df..c0a7459d 100644 --- a/src/extra/oGtk/button.py +++ b/src/extra/oGtk/button.py @@ -94,17 +94,17 @@ class ButtonImage(gtk.Button): def make_button(attrs):return Button(attrs) def make_buttonplay(attrs): - attrs["show"] = "ocarina-pause" - attrs["hide"] = "ocarina-play" + attrs["show"] = ocarina.events.OCARINA_PAUSE + attrs["hide"] = ocarina.events.OCARINA_PLAY attrs["func"] = call.play - attrs["shownow"] = str( not ocarina.vars["$playing"] ).lower() + attrs["shownow"] = str( call.playing() ).lower() return ButtonImage(attrs,gtk.STOCK_MEDIA_PLAY) def make_buttonpause(attrs): - attrs["show"] = "ocarina-play" - attrs["hide"] = "ocarina-pause" + attrs["show"] = ocarina.events.OCARINA_PLAY + attrs["hide"] = ocarina.events.OCARINA_PAUSE attrs["func"] = call.pause - attrs["shownow"] = str( ocarina.vars["$playing"] ).lower() + attrs["shownow"] = str( call.playing() ).lower() return ButtonImage(attrs,gtk.STOCK_MEDIA_PAUSE) def make_buttonstop(attrs): diff --git a/src/extra/oGtk/label.py b/src/extra/oGtk/label.py index 444d8e87..d34bd348 100644 --- a/src/extra/oGtk/label.py +++ b/src/extra/oGtk/label.py @@ -12,6 +12,9 @@ import guibuilder import ocarina import db +from ct import times + + class Label(gtk.Label): def __init__(self,attrs): gtk.Label.__init__(self) @@ -21,11 +24,28 @@ class Label(gtk.Label): self.show() +class TimeLabel(gtk.Label): + def __init__(self,variable): + gtk.Label.__init__(self) + self.variable = variable + ocarina.events.invite(ocarina.events.FILTER_START,self.settime,10000) + ocarina.events.invite(ocarina.events.GUI_DONE,self.settime,10000) + self.show() + + def settime(self): + self.set_text( times.sec2text(self.variable) ) + + +class LabelLibTime(TimeLabel): + def __init__(self): + TimeLabel.__init__(self,ocarina.vars.LIBRARYLENGTH) + + class LabelLibCount(gtk.Label): def __init__(self): gtk.Label.__init__(self) - ocarina.events.invite("ocarina-filter-start",self.setcount,10000) + ocarina.events.invite(ocarina.events.FILTER_START,self.setcount,10000) #ocarina.events.invite("ocarina-gui-done",self.setcount,10000) def setcount(self): @@ -68,31 +88,31 @@ class Label2(gtk.Alignment): class SongTitleLabel(Label2): def __init__(self): Label2.__init__(self,13000, 700) - ocarina.events.invite("tags-changed", self.setTitle) + ocarina.events.invite(ocarina.events.TAGS_CHANGED, self.setTitle) self.setTitle() def setTitle(self): - self.set_text(ocarina.vars["$title"]) + self.set_text(ocarina.vars.TITLE) class SongAlbumLabel(Label2): def __init__(self): Label2.__init__(self,10000, 400) - ocarina.events.invite("tags-changed", self.setAlbum) + ocarina.events.invite(ocarina.events.TAGS_CHANGED, self.setAlbum) self.setAlbum() def setAlbum(self): - self.set_text("from " + ocarina.vars["$album"]) + self.set_text("from " + ocarina.vars.ALBUM) class SongArtistLabel(Label2): def __init__(self): Label2.__init__(self,10000, 400) - ocarina.events.invite("tags-changed", self.setArtist) + ocarina.events.invite(ocarina.events.TAGS_CHANGED, self.setArtist) self.setArtist() def setArtist(self): - self.set_text("by " + ocarina.vars["$artist"]) + self.set_text("by " + ocarina.vars.ARTIST) @@ -101,8 +121,10 @@ def make_libcountlabel(attrs):return LabelLibCount() def make_titlelabel(attrs):return SongTitleLabel() def make_albumlabel(attrs):return SongAlbumLabel() def make_artistlabel(attrs):return SongArtistLabel() +def make_libtimelabel(attrs):return LabelLibTime() guibuilder.parts["label"] = make_label guibuilder.parts["libcountlabel"] = make_libcountlabel +guibuilder.parts["libtimelabel"] = make_libtimelabel guibuilder.parts["titlelabel"] = make_titlelabel guibuilder.parts["albumlabel"] = make_albumlabel guibuilder.parts["artistlabel"] = make_artistlabel \ No newline at end of file diff --git a/src/extra/oGtk/list.py b/src/extra/oGtk/list.py index d8bc2477..f0ad87b2 100644 --- a/src/extra/oGtk/list.py +++ b/src/extra/oGtk/list.py @@ -21,7 +21,8 @@ class SongList(gtk.TreeView): def __init__(self): gtk.TreeView.__init__(self) self.countvar = None - ocarina.events.invite("ocarina-filter-start",self.filter) + self.timevar = None + ocarina.events.invite(ocarina.events.FILTER_START,self.filter) self.list = gtk.ListStore(int,str,str,str,str,int) self.set_reorderable(True) @@ -35,7 +36,7 @@ class SongList(gtk.TreeView): col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) col.set_min_width(2) col.set_max_width(700) - col.set_fixed_width(150) + col.set_fixed_width(200) col.set_sort_indicator(True) if cols[i] != "Id": self.append_column(col) @@ -52,13 +53,18 @@ class SongList(gtk.TreeView): #self.add(self.tree) self.filterModel = self.list.filter_new() self.filterModel.set_visible_func(self.setvisible) - #self.show_all() + self.sort = gtk.TreeModelSort(self.filterModel) + self.set_model(self.sort) + #self.set_model(self.list) + #self.show() + self.show_all() # Add a row to the list def insert(self,trackid): file = list(db.gettrack(trackid)) + ocarina.vars[self.timevar] += file[2] file[2] = times.ftime(file[2]) self.list.append(file) if self.countvar != None: @@ -67,16 +73,19 @@ class SongList(gtk.TreeView): def filter(self): text = ocarina.vars["$filterText"] + ocarina.vars[self.timevar] = 0 self.results = index.search(ocarina.vars["$filterText"]) if self.countvar != None: ocarina.vars[self.countvar] = len(self.results) self.filterModel.refilter() + for row in self.sort: + ocarina.vars[self.timevar] += times.hms2sec(row[2]) - def setvisible(self,list,iter): + def setvisible(self,songlist,iter): if ocarina.vars["$filterText"] == "": return True - if (list[iter][0] in self.results) == True: + if (songlist[iter][0] in self.results) == True: return True return False @@ -86,9 +95,6 @@ class SongList(gtk.TreeView): path = db.getpath(trid) load(path) play() - #cmd.run("load "+path) - #cmd.run("play") - #print self.sort[index][1],self.sort[index][0] @@ -96,11 +102,14 @@ class LibraryList(SongList): def __init__(self): SongList.__init__(self) self.countvar = "$libcount" - ocarina.vars["$libcount"] = 0 - ocarina.events.invite("ocarina-gui-done",self.populate) + self.timevar = "$LibraryLength" + ocarina.vars.LIBCOUNT = 0 + ocarina.vars.LIBRARYLENGTH = 0 + ocarina.events.invite(ocarina.events.GUI_DONE,self.populate) def populate(self): + ocarina.events.start("ocarina-filter-start") thread = needle.Needle(self.insertLibrary) thread.start() #self.insertLibrary() @@ -109,20 +118,20 @@ class LibraryList(SongList): def insertLibrary(self): # Freeze the model before inserting a lot of rows # this speeds up performance + self.hide() self.freeze_child_notify() self.set_model(None) try: libid = db.libid("Music") - ocarina.events.start("ocarina-filter-start") for track in db.getsongs(libid): self.insert(track[1]) except Exception,e: print e - self.sort = gtk.TreeModelSort(self.filterModel) + ocarina.events.start("ocarina-filter-start") self.set_model(self.sort) # Unfreeze the model self.thaw_child_notify() - self.show_all() + self.show() diff --git a/src/extra/oGtk/menu.py b/src/extra/oGtk/menu.py index 2f90fa4c..35b4f341 100644 --- a/src/extra/oGtk/menu.py +++ b/src/extra/oGtk/menu.py @@ -59,8 +59,8 @@ class MenuItem(gtk.MenuItem): class MenuPlay(gtk.ImageMenuItem): def __init__(self): gtk.ImageMenuItem.__init__(self,gtk.STOCK_MEDIA_PLAY) - ocarina.events.invite("ocarina-play",self.hide) - ocarina.events.invite("ocarina-pause",self.show) + ocarina.events.invite(ocarina.events.OCARINA_PLAY,self.hide) + ocarina.events.invite(ocarina.events.OCARINA_PAUSE,self.show) self.connect("activate",self.clicked) self.show() @@ -73,8 +73,8 @@ class MenuPlay(gtk.ImageMenuItem): class MenuPause(gtk.ImageMenuItem): def __init__(self): gtk.ImageMenuItem.__init__(self,gtk.STOCK_MEDIA_PAUSE) - ocarina.events.invite("ocarina-pause",self.hide) - ocarina.events.invite("ocarina-play",self.show) + ocarina.events.invite(ocarina.events.OCARINA_PAUSE,self.hide) + ocarina.events.invite(ocarina.events.OCARINA_PLAY,self.show) self.connect("activate",self.clicked) def clicked(self,item): @@ -85,8 +85,8 @@ class MenuPause(gtk.ImageMenuItem): class MenuStop(gtk.ImageMenuItem): def __init__(self): gtk.ImageMenuItem.__init__(self,gtk.STOCK_MEDIA_STOP) - ocarina.events.invite("ocarina-pause",self.hide) - ocarina.events.invite("ocarina-play",self.show) + ocarina.events.invite(ocarina.events.OCARINA_PAUSE,self.hide) + ocarina.events.invite(ocarina.events.OCARINA_PLAY,self.show) self.connect("activate",self.clicked) def clicked(self,item): @@ -123,35 +123,35 @@ class MenuLibNew(gtk.MenuItem): -class MenuTheme(gtk.MenuItem): - def __init__(self): - gtk.MenuItem.__init__(self,"Change Theme") - self.connect("activate", self.onclick) - self.show() - - def onclick(self,menu): - file = dialog.FileChooser("Select a theme file").choose() - if file!=None: - #print file - ocarina.vars["$theme"] = str(file) - guibuilder.init() +#class MenuTheme(gtk.MenuItem): +# def __init__(self): +# gtk.MenuItem.__init__(self,"Change Theme") +# self.connect("activate", self.onclick) +# self.show() +# +# def onclick(self,menu): +# file = dialog.FileChooser("Select a theme file").choose() +# if file!=None: +# #print file +# ocarina.vars["$theme"] = str(file) +# guibuilder.init() -def make_menubar(attrs=None):return MenuBar() -def make_menuitem(attrs=None):return MenuItem(attrs) -def make_menuplay(attrs=None):return MenuPlay() -def make_menupause(attrs=None):return MenuPause() -def make_menustop(attrs=None):return MenuStop() -def make_menusongsel(attrs=None):return MenuSongSelect() -def make_menulibnew(attrs=None):return MenuLibNew() -def make_menutheme(attrs=None):return MenuTheme() +#def make_menubar(attrs=None):return MenuBar() +#def make_menuitem(attrs=None):return MenuItem(attrs) +#def make_menuplay(attrs=None):return MenuPlay() +#def make_menupause(attrs=None):return MenuPause() +#def make_menustop(attrs=None):return MenuStop() +#def make_menusongsel(attrs=None):return MenuSongSelect() +#def make_menulibnew(attrs=None):return MenuLibNew() +#def make_menutheme(attrs=None):return MenuTheme() -guibuilder.parts["menu-bar"] = make_menubar -guibuilder.parts["menuitem"] = make_menuitem -guibuilder.parts["menuplay"] = make_menuplay -guibuilder.parts["menupause"] = make_menupause -guibuilder.parts["menustop"] = make_menustop -guibuilder.parts["menusongsel"] = make_menusongsel -guibuilder.parts["menulibnew"] = make_menulibnew -guibuilder.parts["menutheme"] = make_menutheme \ No newline at end of file +#guibuilder.parts["menu-bar"] = make_menubar +#guibuilder.parts["menuitem"] = make_menuitem +#guibuilder.parts["menuplay"] = make_menuplay +#guibuilder.parts["menupause"] = make_menupause +#guibuilder.parts["menustop"] = make_menustop +#guibuilder.parts["menusongsel"] = make_menusongsel +#guibuilder.parts["menulibnew"] = make_menulibnew +#guibuilder.parts["menutheme"] = make_menutheme \ No newline at end of file diff --git a/src/extra/oGtk/progbar.py b/src/extra/oGtk/progbar.py index 68248844..df78eeac 100644 --- a/src/extra/oGtk/progbar.py +++ b/src/extra/oGtk/progbar.py @@ -58,8 +58,8 @@ class LibScanBar(gtk.ProgressBar): def __init__(self): gtk.ProgressBar.__init__(self) gobject.timeout_add(500,self.updatebar) - ocarina.events.invite("ocarina-scanlib-start",self.show) - ocarina.events.invite("ocarina-scanlib-stop",self.hide) + ocarina.events.invite(ocarina.events.SCANLIB_START,self.show) + ocarina.events.invite(ocarina.events.SCANLIB_STOP,self.hide) def updatebar(self): diff --git a/src/extra/oGtk/tabs.py b/src/extra/oGtk/tabs.py index 6b07df8b..013621b9 100644 --- a/src/extra/oGtk/tabs.py +++ b/src/extra/oGtk/tabs.py @@ -11,11 +11,40 @@ import gtk import guibuilder class Tabs(gtk.Notebook): - def __init__(self): + def __init__(self,attrs): gtk.Notebook.__init__(self) - self.set_show_border(True) + self.tabPos = gtk.POS_TOP + self.border = True + + for a in attrs: + if a == "tabpos": + if attrs[a] == "left": + self.tabPos = gtk.POS_LEFT + elif attrs[a] == "right": + self.tabPos = gtk.POS_RIGHT + elif attrs[a] == "bottom": + self.tabPos = gtk.POS_BOTTOM + else: + self.tabPos = gtk.POS_TOP + elif a == "border": + if attrs[a] == "False": + self.border = False + + self.set_show_border(False) + self.set_tab_pos(self.tabPos) self.show() -def make_tabs(attrs=None):return Tabs() + def addpage(self,page,label): + # Only rotate labels + if( isinstance(label, gtk.Label) ): + if self.tabPos == gtk.POS_LEFT: + label.set_angle(90) + elif self.tabPos == gtk.POS_RIGHT: + label.set_angle(-90) + + self.append_page(page, label) + + +def make_tabs(attrs=None):return Tabs(attrs) guibuilder.parts["tabs"] = make_tabs diff --git a/src/extra/oGtk/volume.py b/src/extra/oGtk/volume.py index 2f409f22..a1df0511 100644 --- a/src/extra/oGtk/volume.py +++ b/src/extra/oGtk/volume.py @@ -24,14 +24,14 @@ class VolumeControl(gtk.VolumeButton): self.set_relief(relief) adj = self.get_adjustment() - adj.set_page_increment(ocarina.vars["$volumeincr"]) + adj.set_page_increment(ocarina.vars.VOLUMEINCR) self.setValue() self.connect("value-changed",self.valueChanged) self.show() def setValue(self): - self.set_value(ocarina.vars["$volume"]) + self.set_value(ocarina.vars.VOLUME) def valueChanged(self, widget, value): gstreamer.setvol(value) diff --git a/src/extra/ocarina-extra.py b/src/extra/ocarina-extra.py index bd6f85f1..de0ac639 100644 --- a/src/extra/ocarina-extra.py +++ b/src/extra/ocarina-extra.py @@ -6,28 +6,37 @@ __date__ ="$Mar 14, 2010 9:50:09 PM$" import sys sys.path.append("core") - import ocarina -import extradefaults +from ct import path +from ocarina import vars +from ocarina import events + +# Configure additional variables needed for ocarina-extra +vars.THEME = "themes/classic.xml" +vars.FILTERTEXT = "" + +# Make new events +events.create("TAGS_CHANGED") +events.create("FILTER_START") +events.create("GUI_DONE") +events.create("SCANLIB_START") +events.create("SCANLIB_STOP") + + +ocarina.config() from ct.call import write - -#import guibuilder -#from oGtk import * +write("Welcome to Ocarina 3.0 (extra)", 1) import gtk import gobject gobject.threads_init() +import gui +gui.build() +#gui.window.part.show() -def main(): - # Potentially the first thing printed - write("Welcome to Ocarina (extra)", 1) +#ocarina.events.start(ocarina.events.OCARINA_START) - code = ocarina.config() - ocarina.events.start("ocarina-start") - if code == 0: - gtk.main() +gtk.main() - -if __name__ == "__main__":main() diff --git a/src/themes/classic.xml b/src/themes/classic.xml index 7be4d459..bed006b3 100644 --- a/src/themes/classic.xml +++ b/src/themes/classic.xml @@ -50,6 +50,10 @@ + + + + @@ -61,7 +65,12 @@ - + + + + + + diff --git a/src/themes/menu.xml b/src/themes/menu.xml new file mode 100644 index 00000000..bc636061 --- /dev/null +++ b/src/themes/menu.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/themes/simple2.xml b/src/themes/simple2.xml new file mode 100644 index 00000000..0d2c3ad9 --- /dev/null +++ b/src/themes/simple2.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/src/themes/simple3.xml b/src/themes/simple3.xml new file mode 100644 index 00000000..f27f34e8 --- /dev/null +++ b/src/themes/simple3.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + +