Remove Ocarina 4 files
Get them out of the way to begin work on Ocarina 5
24
Makefile
|
@ -1,24 +0,0 @@
|
|||
|
||||
all: ocarina.py
|
||||
./ocarina.py
|
||||
|
||||
ocarina.py:
|
||||
sh scripts/makebin.sh
|
||||
|
||||
clean:
|
||||
rm `find . | grep .pyc`
|
||||
rm ocarina.py
|
||||
|
||||
install:
|
||||
cd /opt/ && git clone git://lavos.homelinux.com/ocarina.git
|
||||
cd /opt/ocarina && make ocarina.py
|
||||
cd /usr/bin && ln -sf /opt/ocarina/bin/ocarina .
|
||||
|
||||
uninstall:
|
||||
rm -rIf /opt/ocarina
|
||||
rm -f /usr/bin/ocarina
|
||||
|
||||
update:
|
||||
cd /opt/ocarina && make clean
|
||||
cd /opt/ocarina && git pull
|
||||
cd /opt/ocarina && make ocarina.py
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/bash
|
||||
cd /opt/ocarina && `which python2` ocarina.py $*
|
|
@ -1,61 +0,0 @@
|
|||
# Bryan Schumaker (11/17/2010)
|
||||
|
||||
from libsaria.sources import library
|
||||
from libsaria import path
|
||||
splitext = path.splitext
|
||||
|
||||
def header(wfile):
|
||||
wfile.write("<html><head>")
|
||||
wfile.write("<script type=\"text/javascript\" src=\"controls.js\"></script>\n")
|
||||
wfile.write("<script type=\"text/javascript\" src=\"utils.js\"></script>\n")
|
||||
wfile.write("<script type=\"text/javascript\">")
|
||||
wfile.write("function playSong(id){")
|
||||
wfile.write("load_id(id);")
|
||||
#wfile.write("var src=id+ext;")
|
||||
#wfile.write("var audio = document.getElementById(\"audio\");")
|
||||
#wfile.write("audio.innerHTML=\"<audio src=\\\"\" + src + \"\\\" controls autoplay></audio>\";")
|
||||
#wfile.write("return false;")
|
||||
wfile.write("}")
|
||||
wfile.write("</script><body>")
|
||||
|
||||
def footer(wfile):
|
||||
wfile.write("</body></html>")
|
||||
|
||||
def body(wfile, args):
|
||||
artist = library.tag_tree[args["artist"]].value
|
||||
album = library.tag_tree[args["artist"]][args["album"]].value
|
||||
wfile.write("<table align=center width=75%>")
|
||||
|
||||
wfile.write("<tr><td><table align=center>")
|
||||
wfile.write("<tr><td><font size=7>%s</font></td></tr>" % album)
|
||||
wfile.write("<tr><td><font size=4>by %s</font></td></tr>" % artist)
|
||||
wfile.write("</table></td></tr>")
|
||||
|
||||
img_ar = artist.replace("/", "%2F")
|
||||
img_al = album.replace("/", "%2F")
|
||||
wfile.write("<tr><td><table align=center width=100%><tr>")
|
||||
wfile.write("<td align=center><table align=center width=100%>")
|
||||
wfile.write("<tr><td align=center>")
|
||||
wfile.write("<img src=\"artwork/%s/%s.jpg\" height=192/></td></tr>" % (img_ar, img_al))
|
||||
wfile.write("<tr><td align=center id=\"audio\"></td></tr></table>")
|
||||
wfile.write("<td align><table align=left>\n")
|
||||
|
||||
titles = []
|
||||
for title, key in library.titles(args["artist"], args["album"]):
|
||||
sid = library.song_id(args["artist"], args["album"], key)
|
||||
track = library.get_attrs(sid, "track")
|
||||
titles += [(track, sid, title)]
|
||||
titles.sort()
|
||||
tags = "<tr><td align=right>%s.</td><td><font onclick=\"playSong('%s');\">%s</font></td></tr>\n"
|
||||
for id, sid, title in titles:
|
||||
wfile.write(tags % (id, sid, title))
|
||||
wfile.write("</table></td>")
|
||||
wfile.write("</tr></table></td></tr>")
|
||||
|
||||
wfile.write("</table>")
|
||||
|
||||
|
||||
def to_html(wfile, args):
|
||||
header(wfile)
|
||||
body(wfile, args)
|
||||
footer(wfile)
|
|
@ -1,92 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<script type="text/javascript" src="utils.js"></script>
|
||||
<script type="text/javascript" src="controls.js"></script>
|
||||
<script type="text/javascript">
|
||||
function set_playing()
|
||||
{
|
||||
var button = document.getElementById("button");
|
||||
button.src = "images/pause.png";
|
||||
button.onclick = pause2;
|
||||
}
|
||||
|
||||
function set_paused()
|
||||
{
|
||||
var button = document.getElementById("button");
|
||||
button.src = "images/play.png";
|
||||
button.onclick = play2;
|
||||
}
|
||||
|
||||
function set_play_button()
|
||||
{
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function()
|
||||
{
|
||||
if (req.readyState == 4 && req.status == 200)
|
||||
{
|
||||
if (req.responseText == "True")
|
||||
{
|
||||
set_playing();
|
||||
} else
|
||||
{
|
||||
set_paused();
|
||||
}
|
||||
}
|
||||
}
|
||||
req.open('GET', "controls.py?a=playing", true);
|
||||
req.send();
|
||||
}
|
||||
|
||||
function set_play_button_repeating()
|
||||
{
|
||||
set_play_button();
|
||||
setTimeout("set_play_button_repeating()", 3000)
|
||||
}
|
||||
|
||||
function play2()
|
||||
{
|
||||
play();
|
||||
set_play_button();
|
||||
}
|
||||
|
||||
function pause2()
|
||||
{
|
||||
pause();
|
||||
set_play_button();
|
||||
}
|
||||
|
||||
function stop2()
|
||||
{
|
||||
stop();
|
||||
set_play_button();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
<tr><td id="title"></td></tr>
|
||||
<tr><td id="artist"></td></tr>
|
||||
<tr><td id="album"></td></tr>
|
||||
</table>
|
||||
<table><tr>
|
||||
<td><img id="button" src="images/play.png" onclick="play2();" /></td>
|
||||
<td><img src="images/stop.png" onclick="stop2();" /></td>
|
||||
<td><img src="images/next.png" onclick="next();" /></td>
|
||||
</tr><tr>
|
||||
<td><img src="images/rewind.png" onclick="rewind();" /></td>
|
||||
<td><img src="images/forward.png" onclick="forward();" /></td>
|
||||
</tr></table>
|
||||
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
set_attr("title", "title");
|
||||
set_attr("artist", "artist");
|
||||
set_attr("album", "album");
|
||||
set_play_button_repeating();
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -1,46 +0,0 @@
|
|||
// Bryan Schumaker (12 / 27 / 2010)
|
||||
|
||||
function control(action)
|
||||
{
|
||||
send_request("RPC/" + action);
|
||||
}
|
||||
|
||||
function play()
|
||||
{
|
||||
control("play");
|
||||
}
|
||||
|
||||
function load_id(id)
|
||||
{
|
||||
control("load&id="+id);
|
||||
}
|
||||
|
||||
function pause()
|
||||
{
|
||||
control("pause");
|
||||
}
|
||||
|
||||
function stop()
|
||||
{
|
||||
control("stop");
|
||||
}
|
||||
|
||||
function next()
|
||||
{
|
||||
control("next");
|
||||
}
|
||||
|
||||
function forward()
|
||||
{
|
||||
control("forward");
|
||||
}
|
||||
|
||||
function rewind()
|
||||
{
|
||||
control("rewind");
|
||||
}
|
||||
|
||||
function play_id(id)
|
||||
{
|
||||
control("play_id/" + id)
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
# Bryan Schumaker (11/18/2010)
|
||||
|
||||
import libsaria.audio
|
||||
import libsaria.sources
|
||||
import ocarina
|
||||
|
||||
controls = libsaria.controls
|
||||
|
||||
play = controls.play
|
||||
pause = controls.pause
|
||||
stop = controls.stop
|
||||
next = controls.next
|
||||
attrs = libsaria.sources.get_attrs
|
||||
load_id = libsaria.sources.library.load_id
|
||||
|
||||
playing = controls.playing
|
||||
forward = controls.seek_forward
|
||||
rewind = controls.seek_backward
|
||||
|
||||
def to_html(wfile, args):
|
||||
action = args["a"]
|
||||
ret = False
|
||||
if action == "play":
|
||||
ret = play()
|
||||
elif action == "pause":
|
||||
ret = pause()
|
||||
elif action == "stop":
|
||||
ret = stop()
|
||||
elif action == "next":
|
||||
ret = next()
|
||||
elif action == "forward":
|
||||
ret = forward()
|
||||
elif action == "rewind":
|
||||
ret = rewind()
|
||||
elif action == "version":
|
||||
ret = ocarina.__vers__
|
||||
elif action == "uptime":
|
||||
ret = ocarina.now() - ocarina.__start__
|
||||
elif action == "title":
|
||||
ret = attrs("title")
|
||||
elif action == "album":
|
||||
ret = "from %s" % attrs("album")
|
||||
elif action == "artist":
|
||||
ret = "by %s" % attrs("artist")
|
||||
elif action == "playing":
|
||||
ret = playing()
|
||||
elif action == "load":
|
||||
load_id(int(args['id']))
|
||||
play()
|
||||
#else:
|
||||
# print action, args
|
||||
wfile.write(str(ret))
|
BIN
html/favicon.ico
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 875 B |
Before Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 837 B |
|
@ -1,20 +0,0 @@
|
|||
<html>
|
||||
<!--<head>
|
||||
<script type="text/javascript" src="utils.js"></script>-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<table>
|
||||
<tr><td><a href="library.html">Library Browser</a></td></tr>
|
||||
<!--<tr><td><a href="library2.py">Library Browser 2</a></td></tr>
|
||||
<tr><td><a href="controls.html">Remote Controls</a></td></tr>
|
||||
<tr><td id="vers"></td><td id="up"></td></tr>-->
|
||||
</table>
|
||||
|
||||
<!--<script type="text/javascript">
|
||||
set_attr_once("version", "vers");
|
||||
set_attr("uptime", "up");
|
||||
</script>-->
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,24 +0,0 @@
|
|||
# Bryan Schumaker
|
||||
import libsaria
|
||||
library = libsaria.sources.library
|
||||
walk = library.walk
|
||||
get_attrs = library.get_attrs
|
||||
|
||||
def header(wfile):
|
||||
wfile.write("<html><body>")
|
||||
|
||||
def footer(wfile):
|
||||
wfile.write("</body></html>")
|
||||
|
||||
def body(wfile):
|
||||
link = "<a href=\"album.py?artist=%s&album=%s\">%s</a><br>"
|
||||
for artist, ar_key in library.artists():
|
||||
wfile.write("<h2>%s</h2>" % artist)
|
||||
for album, al_key in library.albums(ar_key):
|
||||
wfile.write(link % (ar_key, al_key, album))
|
||||
#wfile.write("<a href=\"album.py?artist=\">%s</a><br>" % album)
|
||||
|
||||
def to_html(wfile, args):
|
||||
header(wfile)
|
||||
body(wfile)
|
||||
footer(wfile)
|
|
@ -1,45 +0,0 @@
|
|||
# Bryan Schumaker (12 / 26 / 2010)
|
||||
|
||||
import libsaria
|
||||
library = libsaria.sources.library
|
||||
walk = library.walk
|
||||
get_attrs = library.get_attrs
|
||||
|
||||
cols = [("Title", 400), ("Length", 60), ("Artist", 200), ("Album", 200), ("Year", 50)]
|
||||
|
||||
def header(wfile):
|
||||
wfile.write("<html><body>")
|
||||
|
||||
def footer(wfile):
|
||||
wfile.write("</body></html>")
|
||||
|
||||
def content_header(wfile):
|
||||
wfile.write("<table><tr>")
|
||||
for col, width in cols:
|
||||
wfile.write("<td style=\"width:%spx;\">%s</td>" % (width, col))
|
||||
wfile.write("</tr></table>")
|
||||
wfile.write("<hr>")
|
||||
|
||||
def body(wfile):
|
||||
wfile.write("header stuff goes here")
|
||||
content_header(wfile)
|
||||
wfile.write("<div style=\"height:80%;width:100%;overflow:auto;\">")
|
||||
wfile.write("<table>")
|
||||
colors = ["white", "aliceblue"]
|
||||
i = 0
|
||||
for id in walk():
|
||||
wfile.write("<tr>")
|
||||
for index, attr in enumerate(get_attrs(id, "title", "lenstr", "artist", "album", "year")):
|
||||
wfile.write("<td style=\"width:%spx;background:%s;\">%s</td>" % (cols[index][1], colors[i], attr))
|
||||
wfile.write("</tr>")
|
||||
if i == 0:
|
||||
i = 1
|
||||
else:
|
||||
i = 0
|
||||
wfile.write("</table></div>")
|
||||
wfile.write("footer stuff goes here")
|
||||
|
||||
def to_html(wfile, args):
|
||||
header(wfile)
|
||||
body(wfile)
|
||||
footer(wfile)
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
function message()
|
||||
{
|
||||
document.getElementById("bryan").innerHTML = "Internal javascript test!";
|
||||
}
|
25
html/test.py
|
@ -1,25 +0,0 @@
|
|||
# Bryan Schumaker
|
||||
import libsaria
|
||||
library = libsaria.sources.library
|
||||
walk = library.walk
|
||||
get_attrs = library.get_attrs
|
||||
|
||||
def header(wfile):
|
||||
wfile.write("<html><body>")
|
||||
|
||||
def footer(wfile):
|
||||
wfile.write("</body></html>")
|
||||
|
||||
def body(wfile):
|
||||
wfile.write("<table border=1>")
|
||||
for id in library.walk():
|
||||
#attrs = get_attrs(id, "id", "title", "lenstr", "artist", "album", "year")
|
||||
artist, album, title = library.get_attrs(id, "artist", "album", "title")
|
||||
wfile.write("<tr><td>%s</td><td>%s</td><td>%s</td></tr>" % (artist, album, title))
|
||||
wfile.write("</table>")
|
||||
#wfile.write("Python!!!")
|
||||
|
||||
def to_html(wfile):
|
||||
header(wfile)
|
||||
body(wfile)
|
||||
footer(wfile)
|
|
@ -1,38 +0,0 @@
|
|||
// Bryan Schumaker (12 / 27 / 2010)
|
||||
|
||||
function set_attr(attr, id)
|
||||
{
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function()
|
||||
{
|
||||
if (req.readyState == 4 && req.status == 200)
|
||||
{
|
||||
document.getElementById(id).innerHTML = req.responseText;
|
||||
}
|
||||
}
|
||||
|
||||
req.open('GET', "controls.py?a=" + attr, true);
|
||||
req.send();
|
||||
setTimeout("set_attr(\"" + attr + "\", \"" + id + "\")", 3000)
|
||||
}
|
||||
|
||||
function set_attr_once(attr, id)
|
||||
{
|
||||
var req = new XMLHttpRequest();
|
||||
req.onreadystatechange = function()
|
||||
{
|
||||
if (req.readyState == 4 && req.status == 200)
|
||||
{
|
||||
document.getElementById(id).innerHTML = req.responseText;
|
||||
}
|
||||
}
|
||||
req.open('GET', "controls.py?a=" + attr, true);
|
||||
req.send();
|
||||
}
|
||||
|
||||
function send_request(url)
|
||||
{
|
||||
var http = new XMLHttpRequest();
|
||||
http.open('GET', url, true);
|
||||
http.send();
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<html>
|
||||
|
||||
<body>
|
||||
<table width=100% height=100%><tr>
|
||||
<td align="center" valign="middle">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center"> <u>Select a radio station</u> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"> <a href="http://www.pandora.com">Pandora</a> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center"> <a href="http://www.grooveshark.com">Grooveshark</a> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,35 +0,0 @@
|
|||
# Bryan Schumaker (8/7/2010)
|
||||
|
||||
import version
|
||||
import prefs
|
||||
import audio
|
||||
import path
|
||||
|
||||
import sources
|
||||
import controls
|
||||
import server
|
||||
|
||||
from path import lastfm
|
||||
#plugin = None
|
||||
|
||||
|
||||
def startup():
|
||||
# global plugin
|
||||
# import plugin
|
||||
|
||||
# plugin.load_all()
|
||||
prefs.enable_save()
|
||||
parse_user_input()
|
||||
|
||||
|
||||
def shutdown():
|
||||
audio.shutdown()
|
||||
server.shutdown()
|
||||
## import plugin
|
||||
## plugin.quit()
|
||||
|
||||
|
||||
def parse_user_input():
|
||||
import sys
|
||||
for item in sys.argv[1:]:
|
||||
path.files.universal_open(item)
|
|
@ -1,121 +0,0 @@
|
|||
# Bryan Schumake (8/7/2010)
|
||||
|
||||
import gst
|
||||
import datetime
|
||||
import threading
|
||||
import pipeline
|
||||
from libsaria import callbacks
|
||||
from libsaria import prefs
|
||||
from libsaria import controls
|
||||
|
||||
timedelta = datetime.timedelta
|
||||
audio_lock = threading.Lock()
|
||||
lock_audio = audio_lock.acquire
|
||||
unlock_audio = audio_lock.release
|
||||
|
||||
def shutdown():
|
||||
lock_audio()
|
||||
pipeline.reset()
|
||||
unlock_audio()
|
||||
|
||||
def load_file(file):
|
||||
lock_audio()
|
||||
pipeline.load_file("file", file)
|
||||
unlock_audio()
|
||||
callbacks.load_file(file)
|
||||
|
||||
def get_cur_file():
|
||||
lock_audio()
|
||||
file = pipeline.get_cur_file()
|
||||
unlock_audio()
|
||||
return file
|
||||
|
||||
def get_state():
|
||||
lock_audio()
|
||||
state = pipeline.get_state()
|
||||
unlock_audio()
|
||||
return state
|
||||
|
||||
def is_playing():
|
||||
return get_state() == gst.STATE_PLAYING
|
||||
|
||||
def do_notify_playing():
|
||||
if get_state() == gst.STATE_PLAYING:
|
||||
callbacks.play()
|
||||
|
||||
def play():
|
||||
lock_audio()
|
||||
pipeline.play()
|
||||
unlock_audio()
|
||||
do_notify_playing()
|
||||
|
||||
def do_notify_paused():
|
||||
if get_state() == gst.STATE_PAUSED:
|
||||
callbacks.pause()
|
||||
|
||||
def pause():
|
||||
lock_audio()
|
||||
pipeline.pause()
|
||||
unlock_audio()
|
||||
do_notify_paused()
|
||||
|
||||
def stop():
|
||||
lock_audio()
|
||||
pipeline.stop()
|
||||
unlock_audio()
|
||||
do_notify_paused()
|
||||
|
||||
def seek(amount):
|
||||
lock_audio()
|
||||
pipeline.seek(amount)
|
||||
unlock_audio()
|
||||
|
||||
def seek_prcnt(prcnt):
|
||||
lock_audio()
|
||||
pipeline.seek_prcnt(prcnt)
|
||||
unlock_audio()
|
||||
|
||||
def set_volume(prcnt):
|
||||
lock_audio()
|
||||
pipeline.set_volume(prcnt)
|
||||
unlock_audio()
|
||||
prefs.set("libsaria.audio.volume", prcnt)
|
||||
set_volume(prefs.init("libsaria.audio.volume", 1.0))
|
||||
|
||||
def position():
|
||||
lock_audio()
|
||||
pos = pipeline.position()
|
||||
unlock_audio()
|
||||
return pos
|
||||
|
||||
def duration():
|
||||
lock_audio()
|
||||
dur = pipeline.duration()
|
||||
unlock_audio()
|
||||
return dur
|
||||
|
||||
def make_progstr(spot):
|
||||
sec = spot / 1000000000
|
||||
lenstr = "%s" % timedelta(seconds=sec)
|
||||
if lenstr[0] == "0" and lenstr[1] == ":":
|
||||
lenstr = lenstr[2:]
|
||||
else:
|
||||
lenstr = lenstr
|
||||
return lenstr.split(".")[0]
|
||||
|
||||
def get_progstr():
|
||||
return make_progstr(position())
|
||||
|
||||
def get_time_at(prcnt):
|
||||
return make_progstr(duration() * prcnt)
|
||||
|
||||
def get_progress():
|
||||
dur = duration()
|
||||
if dur > 0.0:
|
||||
return position() / dur
|
||||
return 0.0
|
||||
|
||||
def bus_message(bus, message):
|
||||
if message.type == gst.MESSAGE_EOS:
|
||||
controls.catch_eos()
|
||||
pipeline.bus.connect("message", bus_message)
|
|
@ -1,80 +0,0 @@
|
|||
# Bryan Schumaker (2 / 6 / 2011)
|
||||
# NOTE: DO NOT CALL FUNCTIONS IN THIS FILE DIRECTLY
|
||||
# USE THE FUNCTIONS IN __init__.py INSTEAD. THIS
|
||||
# WILL ENSURE THAT THE AUDIO LOCK IS HELD :-)
|
||||
|
||||
import gst
|
||||
|
||||
player = gst.element_factory_make("playbin2", "player")
|
||||
time = gst.Format(gst.FORMAT_TIME)
|
||||
bus = player.get_bus()
|
||||
bus.add_signal_watch()
|
||||
|
||||
cur_file = None
|
||||
|
||||
def reset():
|
||||
global cur_file
|
||||
cur_file = None
|
||||
player.set_state(gst.STATE_NULL)
|
||||
|
||||
def load_file(type, file):
|
||||
global cur_file
|
||||
reset()
|
||||
cur_file = file
|
||||
player.set_property("uri", "%s://%s" % (type, file))
|
||||
|
||||
def get_cur_file():
|
||||
return cur_file
|
||||
|
||||
def has_file():
|
||||
return cur_file != None
|
||||
|
||||
def change_state(state):
|
||||
if has_file() == True:
|
||||
player.set_state(state)
|
||||
else:
|
||||
player.set_state(gst.STATE_NULL)
|
||||
|
||||
def play():
|
||||
change_state(gst.STATE_PLAYING)
|
||||
|
||||
def pause():
|
||||
change_state(gst.STATE_PAUSED)
|
||||
|
||||
def stop():
|
||||
pause()
|
||||
seek_to(0)
|
||||
|
||||
def get_state():
|
||||
return player.get_state()[1]
|
||||
|
||||
def position():
|
||||
if get_state() == gst.STATE_NULL:
|
||||
pos = 0.0
|
||||
else:
|
||||
pos = player.query_position(time)[0]
|
||||
return float(pos)
|
||||
|
||||
def duration():
|
||||
if get_state() == gst.STATE_NULL:
|
||||
dur = 0.0
|
||||
else:
|
||||
dur = player.query_duration(time)[0]
|
||||
return float(dur)
|
||||
|
||||
def seek_to(new_spot):
|
||||
if new_spot < 0:
|
||||
new_spot = 0
|
||||
player.seek_simple(time, gst.SEEK_FLAG_FLUSH, new_spot)
|
||||
|
||||
def seek(amount):
|
||||
pos = position()
|
||||
if pos == 0.0:
|
||||
return
|
||||
seek_to( pos + (amount * 1000000000) )
|
||||
|
||||
def seek_prcnt(prcnt):
|
||||
seek_to(prcnt * duration())
|
||||
|
||||
def set_volume(prcnt):
|
||||
player.set_property("volume", prcnt)
|
|
@ -1,47 +0,0 @@
|
|||
# Bryan Schumaker (4 / 30 / 2011)
|
||||
|
||||
import libsaria
|
||||
|
||||
def null_cb(*args):
|
||||
pass
|
||||
|
||||
on_play = null_cb
|
||||
def play():
|
||||
on_play()
|
||||
|
||||
on_pause = null_cb
|
||||
def pause():
|
||||
on_pause()
|
||||
|
||||
on_load = null_cb
|
||||
def load_file(file):
|
||||
attrs = libsaria.sources.all_attrs()
|
||||
on_load(file, attrs)
|
||||
|
||||
on_like = null_cb
|
||||
def like_song(like):
|
||||
on_like(like)
|
||||
|
||||
on_set_volume = null_cb
|
||||
def set_volume(prcnt):
|
||||
on_set_volume(prcnt)
|
||||
|
||||
on_get_art = null_cb
|
||||
def get_art(file, id):
|
||||
on_get_art(file, id)
|
||||
|
||||
on_load_playlist = null_cb
|
||||
def load_playlist():
|
||||
on_load_playlist()
|
||||
|
||||
on_library_updated = null_cb
|
||||
def library_updated():
|
||||
on_library_updated()
|
||||
|
||||
on_queue_changed = null_cb
|
||||
def queue_changed():
|
||||
on_queue_changed()
|
||||
|
||||
on_filter = null_cb
|
||||
def refilter():
|
||||
on_refilter()
|
|
@ -1,80 +0,0 @@
|
|||
# Bryan Schumaker (11/23/2010)
|
||||
|
||||
import prefs
|
||||
import audio
|
||||
import libsaria
|
||||
from libsaria import path
|
||||
from libsaria import sources
|
||||
from libsaria import callbacks
|
||||
|
||||
expand = path.expand
|
||||
exists = path.exists
|
||||
|
||||
pause_after = False
|
||||
prefs.init("libsaria.random", False)
|
||||
|
||||
def pick_next():
|
||||
global pause_after
|
||||
file = sources.next()
|
||||
if file != None:
|
||||
load(file)
|
||||
if pause_after == True:
|
||||
pause()
|
||||
else:
|
||||
play()
|
||||
pause_after = False
|
||||
|
||||
def catch_eos(*args):
|
||||
libsaria.sources.inc_count()
|
||||
pick_next()
|
||||
|
||||
def next():
|
||||
pick_next()
|
||||
|
||||
def play():
|
||||
audio.play()
|
||||
|
||||
def pause():
|
||||
audio.pause()
|
||||
|
||||
def playing():
|
||||
return audio.get_state() == audio.gst.STATE_PLAYING
|
||||
|
||||
def do_pause_after(*args):
|
||||
global pause_after
|
||||
pause_after = True
|
||||
|
||||
def toggle_play():
|
||||
if audio.get_state() == audio.gst.STATE_PAUSED:
|
||||
play()
|
||||
else:
|
||||
pause()
|
||||
|
||||
def stop():
|
||||
audio.stop()
|
||||
|
||||
def seek_forward():
|
||||
libsaria.audio.seek(5)
|
||||
|
||||
def seek_backward():
|
||||
libsaria.audio.seek(-5)
|
||||
|
||||
def set_volume(prcnt):
|
||||
audio.set_volume(prcnt)
|
||||
callbacks.set_volume(prcnt)
|
||||
|
||||
def set_rand(rand):
|
||||
prefs.set("libsaria.random", rand)
|
||||
|
||||
def set_like(like=None):
|
||||
sources.set_attr("like", like)
|
||||
callbacks.like_song(like)
|
||||
|
||||
def get_like():
|
||||
return sources.all_attrs()["like"]
|
||||
|
||||
def load(file):
|
||||
file = expand(file)
|
||||
if not exists(file):
|
||||
return False
|
||||
audio.load_file(file)
|
|
@ -1,57 +0,0 @@
|
|||
# Bryan Schumaker (8/7/2010)
|
||||
|
||||
import libsaria
|
||||
import os
|
||||
|
||||
exists = os.path.exists
|
||||
is_dir = os.path.isdir
|
||||
expand = os.path.expanduser
|
||||
splitext = os.path.splitext
|
||||
basename = os.path.basename
|
||||
join = os.path.join
|
||||
makedir = os.mkdir
|
||||
rm = os.remove
|
||||
ls = os.listdir
|
||||
walk = os.walk
|
||||
sep = os.sep
|
||||
cwd = os.getcwd
|
||||
stat = os.stat
|
||||
|
||||
cp = None
|
||||
saria_dir = None
|
||||
plugin_dir = None
|
||||
|
||||
shutil = None
|
||||
FSTree = None
|
||||
s_dir = None
|
||||
p_dir = None
|
||||
|
||||
def file_id(path):
|
||||
if exists(path):
|
||||
return stat(path).st_ino
|
||||
return -1
|
||||
|
||||
def saria_dir_once():
|
||||
global s_dir
|
||||
global saria_dir
|
||||
s_dir = join(expand("~"), ".saria")
|
||||
if exists(s_dir) == False:
|
||||
mkdir(s_dir)
|
||||
saria_dir = saria_dir_rest
|
||||
return s_dir
|
||||
def saria_dir_rest():
|
||||
global s_dir
|
||||
return s_dir
|
||||
saria_dir = saria_dir_once
|
||||
|
||||
def cp_once(src, dest):
|
||||
global cp
|
||||
global shutil
|
||||
import shutil
|
||||
cp = shutil.copy
|
||||
cp(src, dest)
|
||||
cp = cp_once
|
||||
|
||||
def mkdir(path):
|
||||
if not exists(path):
|
||||
makedir(path)
|
|
@ -1,99 +0,0 @@
|
|||
# Bryan Schumaker (11/12/2010)
|
||||
|
||||
import libsaria
|
||||
from libsaria import path
|
||||
from libsaria.sources import playlist
|
||||
from libsaria import version
|
||||
from libsaria import callbacks
|
||||
import libsaria.xm as xml
|
||||
|
||||
add_child = xml.add_child
|
||||
add_text = xml.add_text
|
||||
get_attrs = libsaria.sources.library.get_attrs
|
||||
file_id = path.file_id
|
||||
lib_file = "library"
|
||||
vers = "%s.%s" % (version.__major__, version.__minor__)
|
||||
if version.__dev__ == True:
|
||||
lib_file = lib_file + "-dev"
|
||||
lib_file += ".xml"
|
||||
lib_file = path.join(path.saria_dir(), lib_file)
|
||||
|
||||
xml_children = xml.children
|
||||
xml_child = xml.child
|
||||
xml_attrs = xml.attributes
|
||||
|
||||
#######################################
|
||||
# Generic encode and decode functions #
|
||||
#######################################
|
||||
|
||||
def decode_attr(attr):
|
||||
child = xml.child(attr)
|
||||
return (attr.nodeName, child.data.strip())
|
||||
|
||||
def encode_attr(doc, node, attr, value):
|
||||
child = add_child(doc, node, attr)
|
||||
add_text(doc, child, value)
|
||||
|
||||
def encode_track(doc, node, id):
|
||||
filepath, like, count = get_attrs(id, "filepath", "like", "count")
|
||||
if (like == None) and (count == 0):
|
||||
return
|
||||
child = add_child(doc, node, "track", {"like":like, "count":count})
|
||||
add_text(doc, child, filepath)
|
||||
|
||||
##################################
|
||||
# xspf encode / decode functions #
|
||||
##################################
|
||||
|
||||
def decode_xspf_track(location):
|
||||
file = xml.child(location).data.strip()
|
||||
if file[:7] == "file://":
|
||||
id = path.file_id(file[7:])
|
||||
playlist.add_ids([id])
|
||||
|
||||
def decode_xspf(child):
|
||||
tlist = xml.child(child)
|
||||
playlist.reset()
|
||||
for node in xml.children(tlist):
|
||||
try:
|
||||
loc = xml.get_elements(node, "location")[0]
|
||||
decode_xspf_track(loc)
|
||||
except:
|
||||
pass
|
||||
playlist.save()
|
||||
callbacks.load_playlist()
|
||||
|
||||
def encode_xspf(doc, node, id):
|
||||
filepath = get_attrs(id, "filepath")[0]
|
||||
track = add_child(doc, node, "track")
|
||||
location = add_child(doc, track, "location")
|
||||
add_text(doc, location, "file://%s" % filepath)
|
||||
|
||||
|
||||
#############################################
|
||||
# Control will enter the export module here #
|
||||
#############################################
|
||||
|
||||
def save_playlist(filepath):
|
||||
file, ext = path.splitext(filepath)
|
||||
if ext != ".xml":
|
||||
filepath+=".xml"
|
||||
|
||||
doc = xml.new()
|
||||
child = add_child(doc, doc, "playlist", {"version":1, "xmlns":"http://xspf.org/ns/0/"})
|
||||
tlist = add_child(doc, child, "trackList")
|
||||
|
||||
for id in playlist.list_ids():
|
||||
encode_xspf(doc, tlist, id)
|
||||
|
||||
fout = open(filepath, 'w')
|
||||
fout.write(doc.toprettyxml())
|
||||
fout.close()
|
||||
print "Wrote playlist to: %s" % filepath
|
||||
|
||||
def import_xml(file):
|
||||
fin = open(file)
|
||||
doc = xml.parse(fin)
|
||||
child = xml.child(doc)
|
||||
if child.nodeName == "playlist":
|
||||
decode_xspf(child)
|
|
@ -1,42 +0,0 @@
|
|||
# Bryan Schumaker (8/7/2010)
|
||||
|
||||
import libsaria
|
||||
from libsaria import path
|
||||
from libsaria import version
|
||||
plugin = None
|
||||
export = None
|
||||
|
||||
dev = ""
|
||||
if version.__dev__ == True:
|
||||
dev = "-dev"
|
||||
|
||||
def open_plugin(file):
|
||||
global plugin
|
||||
if plugin == None:
|
||||
from libsaria import plugin
|
||||
plugin.install(file)
|
||||
|
||||
def open_xml(file):
|
||||
global export
|
||||
if export == None:
|
||||
import export
|
||||
export.import_xml(file)
|
||||
|
||||
def open_music(file):
|
||||
try:
|
||||
libsaria.sources.cur_id = None
|
||||
libsaria.controls.load(file)
|
||||
libsaria.controls.play()
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
mapping = {".py":open_plugin, ".xml":open_xml}
|
||||
def universal_open(file):
|
||||
file = file.replace("%20", " ")
|
||||
file = file.replace("%22", "\"")
|
||||
if path.is_dir(file):
|
||||
libsaria.sources.make_library(file)
|
||||
return
|
||||
base, ext = path.splitext(file)
|
||||
func = mapping.get(ext, open_music)
|
||||
func(file)
|
|
@ -1,85 +0,0 @@
|
|||
# Bryan Schumaker (10/24/2010)
|
||||
|
||||
import libsaria
|
||||
from libsaria import sources
|
||||
from libsaria import web
|
||||
from libsaria import xm
|
||||
from libsaria import callbacks
|
||||
from libsaria import storage
|
||||
from libsaria.storage import cache
|
||||
import threading
|
||||
|
||||
file_id = libsaria.path.file_id
|
||||
pref_attr = xm.find_preferred_attribute
|
||||
|
||||
pref_sizes = ["extralarge", "large", "medium", "small"]
|
||||
|
||||
APIROOT = "http://ws.audioscrobbler.com/2.0/"
|
||||
APIKEY = "2c76f85a6704efd74b5a358821284ef9"
|
||||
SECRET = "3a6012bfb627b60a884cf33fc044885c"
|
||||
|
||||
|
||||
class LastFmRequest(dict):
|
||||
def __init__(self, method):
|
||||
self.method = method
|
||||
|
||||
def print_file(self, file):
|
||||
for line in file:
|
||||
print line.strip()
|
||||
file.seek(0)
|
||||
|
||||
def place(self, printfile=False):
|
||||
url = web.Url(APIROOT + "?method=" + self.method)
|
||||
url["api_key"] = APIKEY
|
||||
for param in self:
|
||||
url[param] = self[param]
|
||||
try:
|
||||
file = url.open()
|
||||
except:
|
||||
return None
|
||||
if file == None:
|
||||
return None
|
||||
if printfile==True:
|
||||
self.print_file(file)
|
||||
doc = xm.parse( file )
|
||||
lfm = xm.child(doc)
|
||||
if xm.attributes(lfm)["status"] == "ok":
|
||||
return xm.child(lfm)
|
||||
else:
|
||||
return None
|
||||
|
||||
def lfm_cache_album(artist, album, title):
|
||||
req = LastFmRequest("album.getInfo")
|
||||
req["album"] = album
|
||||
req["artist"] = artist
|
||||
doc = req.place()
|
||||
if doc == None:
|
||||
return False
|
||||
node = pref_attr(doc, "image", "size", pref_sizes)
|
||||
node = xm.child(node)
|
||||
if node == None:
|
||||
return
|
||||
try:
|
||||
url = web.Url(node.data)
|
||||
text = url.open().read()
|
||||
return text
|
||||
except:
|
||||
pass
|
||||
return None
|
||||
|
||||
def get_album_art(attrs):
|
||||
file = cache.get_item(attrs["artist"], attrs["album"], attrs["title"], "Folder.jpg", lfm_cache_album, "images/ocarina.png")
|
||||
if file != None:
|
||||
callbacks.get_art(file, attrs["id"])
|
||||
|
||||
def get_artwork(attrs):
|
||||
threading.Thread(target=get_album_art, args=(attrs,)).start()
|
||||
|
||||
def test_artwork(attrs):
|
||||
path = cache.test_item(attrs["artist"], attrs["album"], "Folder.jpg", "images/ocarina.png")
|
||||
if path == "images/ocarina.png":
|
||||
get_artwork(attrs)
|
||||
return path
|
||||
|
||||
def set_artwork(artist, album, img_path):
|
||||
cache.copy_in_file(artist, album, "Folder.jpg", img_path)
|
|
@ -1,106 +0,0 @@
|
|||
# Bryan Schumaker (8/15/2010)
|
||||
|
||||
# Lazy loaded modules
|
||||
path = None
|
||||
imp = None
|
||||
|
||||
# Runtime variables
|
||||
p_dir = None
|
||||
loaded = dict()
|
||||
|
||||
# Function variables
|
||||
install = None
|
||||
load_all = None
|
||||
load_plugin = None
|
||||
|
||||
|
||||
def init():
|
||||
global path
|
||||
global p_dir
|
||||
if path == None:
|
||||
from libsaria import path
|
||||
if p_dir == None:
|
||||
p_dir = path.plugin_dir()
|
||||
|
||||
def quit():
|
||||
global loaded
|
||||
for mod in loaded:
|
||||
try:
|
||||
loaded[mod].stop()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def install_once(filepath):
|
||||
global install
|
||||
init()
|
||||
install = install_rest
|
||||
install(filepath)
|
||||
def install_rest(filepath):
|
||||
global p_dir
|
||||
global path
|
||||
split = filepath.rsplit(path.sep, 1)
|
||||
file = split[len(split)-1]
|
||||
dest = path.join(p_dir, file)
|
||||
path.cp(filepath, dest)
|
||||
split = path.splitext(file)
|
||||
if split[len(split)-1] == ".py":
|
||||
name = split[0]
|
||||
load_plugin(name, dest)
|
||||
install = install_once
|
||||
|
||||
|
||||
def load_all_once():
|
||||
global load_all
|
||||
init()
|
||||
load_all = load_all_rest
|
||||
load_all()
|
||||
def load_all_rest():
|
||||
global load_plugin
|
||||
global path
|
||||
global p_dir
|
||||
for file in path.ls(p_dir):
|
||||
split = path.splitext(file)
|
||||
if split[len(split)-1] == ".py":
|
||||
load_plugin(split[0], path.join(p_dir, file))
|
||||
load_all = load_all_once
|
||||
|
||||
|
||||
def load_plugin_once(name, file):
|
||||
global load_plugin
|
||||
global imp
|
||||
import imp
|
||||
load_plugin = load_plugin_rest
|
||||
load_plugin(name, file)
|
||||
def load_plugin_rest(name, file):
|
||||
global imp
|
||||
global path
|
||||
global loaded
|
||||
|
||||
if name in loaded:
|
||||
mod = loaded[name]
|
||||
if hasattr(mod, "stop"):
|
||||
loaded[name].stop()
|
||||
del globals()[name]
|
||||
|
||||
try:
|
||||
mod = imp.load_source(name, file)
|
||||
except Exception, e:
|
||||
print "Error loading plugin: %s" % file
|
||||
print e
|
||||
|
||||
try:
|
||||
if mod.check_version() == False:
|
||||
print "Error: plugin %s requires a different version" % name
|
||||
return
|
||||
except:
|
||||
print "Warning: plugin %s doesn't check versions" % name
|
||||
|
||||
try:
|
||||
globals()[name] = mod
|
||||
loaded[name] = mod
|
||||
mod.start()
|
||||
except Exception, e:
|
||||
print "Error starting plugin: %s" % file
|
||||
print e
|
||||
load_plugin = load_plugin_once
|
|
@ -1,28 +0,0 @@
|
|||
# Bryan Schumaker (4 / 28 / 2011)
|
||||
|
||||
import storage
|
||||
|
||||
FILE = "preferences"
|
||||
prefs = storage.load_obj(FILE, dict)
|
||||
save_enable = False
|
||||
|
||||
def save():
|
||||
if save_enable == True:
|
||||
storage.save_obj(FILE, prefs)
|
||||
|
||||
def enable_save():
|
||||
global save_enable
|
||||
save_enable = True
|
||||
save()
|
||||
|
||||
def get(key):
|
||||
return prefs.get(key, None)
|
||||
|
||||
def set(key, value):
|
||||
prefs[key] = value
|
||||
save()
|
||||
|
||||
def init(key, value):
|
||||
val = prefs.setdefault(key, value)
|
||||
save()
|
||||
return val
|
|
@ -1,41 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
from BaseHTTPServer import HTTPServer
|
||||
import threading
|
||||
|
||||
from libsaria import prefs
|
||||
import request
|
||||
|
||||
server = None
|
||||
PREF_KEY="libsaria.server.enabled"
|
||||
prefs.init(PREF_KEY, False)
|
||||
|
||||
def setup_server():
|
||||
global server
|
||||
if prefs.get(PREF_KEY) == False:
|
||||
return
|
||||
try:
|
||||
server = HTTPServer(('', 4242), request.Handler)
|
||||
server.serve_forever()
|
||||
except Exception,e:
|
||||
print "Error starting server:", e
|
||||
|
||||
def startup():
|
||||
threading.Thread(target=setup_server).start()
|
||||
startup()
|
||||
|
||||
def shutdown():
|
||||
global server
|
||||
if server != None:
|
||||
server.shutdown()
|
||||
server = None
|
||||
|
||||
def get_state():
|
||||
return prefs.get(PREF_KEY)
|
||||
|
||||
def toggle_state(active):
|
||||
prefs.set(PREF_KEY, active)
|
||||
if active == True:
|
||||
startup()
|
||||
else:
|
||||
shutdown()
|
|
@ -1,18 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
import pages
|
||||
|
||||
def format_path(path):
|
||||
if path == "/":
|
||||
path = "/index.html"
|
||||
path = path.split("/")
|
||||
return [cmp for cmp in path if cmp != '']
|
||||
|
||||
def find_file(path):
|
||||
return pages.has_file(path)
|
||||
|
||||
def get_type(path):
|
||||
return pages.file_type(path)
|
||||
|
||||
def send_file(write, path):
|
||||
pages.page_text(write, path)
|
|
@ -1,38 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
import root
|
||||
import rpc
|
||||
|
||||
docs = {}
|
||||
docs.update(root.docs)
|
||||
docs.update(rpc.docs)
|
||||
|
||||
types = {
|
||||
"html":"text/html",
|
||||
"js":"text/javascript",
|
||||
}
|
||||
|
||||
def lookup(file):
|
||||
doc = docs
|
||||
for i, cmp in enumerate(file):
|
||||
doc = doc.get(cmp, None)
|
||||
if doc == None:
|
||||
break
|
||||
elif len(doc) == 2:
|
||||
break
|
||||
return doc, i + 1
|
||||
|
||||
def has_file(file):
|
||||
doc, index = lookup(file)
|
||||
return doc != None
|
||||
|
||||
def file_type(file):
|
||||
(func, type), index = lookup(file)
|
||||
return type
|
||||
|
||||
def page_text(write, file):
|
||||
(func, type), index = lookup(file)
|
||||
if len(file) > index:
|
||||
res = func(write, file[index:])
|
||||
else:
|
||||
res = func(write)
|
|
@ -1,44 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
from libsaria import sources
|
||||
|
||||
SCRIPT = "<script type=\"text/javascript\" src=\"%s\"></script>"
|
||||
|
||||
def write_file(write, file):
|
||||
f = open(file)
|
||||
write(f.read())
|
||||
f.close()
|
||||
|
||||
def index(write):
|
||||
write_file(write, "html/index.html")
|
||||
|
||||
def library(write):
|
||||
write("<html><head>")
|
||||
write(SCRIPT % "controls.js")
|
||||
write(SCRIPT % "utils.js")
|
||||
write("</head><body><table>\n")
|
||||
color = "white"
|
||||
get_attrs = sources.library.get_attrs
|
||||
for id in sources.library.list_ids():
|
||||
title, artist, album = get_attrs(id, "title", "artist", "album")
|
||||
write("<tr style=\"background:%s\" ondblclick=play_id(%s)>" % (color, id))
|
||||
write("<td><a href=\"RPC/play_id/%s\" onclick=\"play_id(%s);return false\">%s</a></td>" % (id, id, title))
|
||||
write("<td>%s</td><td>%s</td>\n" % (artist, album))
|
||||
if color == "white":
|
||||
color = "aliceblue"
|
||||
else:
|
||||
color = "white"
|
||||
write("</table></body></html>")
|
||||
|
||||
def controls(write):
|
||||
write_file(write, "html/controls.js")
|
||||
|
||||
def utils(write):
|
||||
write_file(write, "html/utils.js")
|
||||
|
||||
docs = {
|
||||
"index.html":(index, "html"),
|
||||
"library.html":(library, "html"),
|
||||
"controls.js":(controls, "js"),
|
||||
"utils.js":(utils, "js"),
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
from libsaria import sources
|
||||
from libsaria import controls
|
||||
|
||||
def play(write):
|
||||
controls.play()
|
||||
|
||||
def pause(write):
|
||||
controls.pause()
|
||||
|
||||
def play_id(write, id):
|
||||
sources.play_id(long(id[0]))
|
||||
|
||||
rpc = {
|
||||
"play.html":(play, "html"),
|
||||
"pause.html":(pause, "html"),
|
||||
"play_id":(play_id, "html"),
|
||||
}
|
||||
|
||||
docs = {
|
||||
"RPC":rpc,
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
# Bryan Schumaker (5 / 15 / 2011)
|
||||
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler
|
||||
import files
|
||||
|
||||
class Handler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
path = files.format_path(self.path)
|
||||
if not files.find_file(path):
|
||||
self.send_error(404, "File Not Found: %s" % path)
|
||||
return
|
||||
|
||||
type = files.get_type(path)
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', type)
|
||||
self.end_headers()
|
||||
|
||||
files.send_file(self.wfile.write, path)
|
||||
self.wfile.close()
|
|
@ -1,137 +0,0 @@
|
|||
# Bryan Schumaker (8/8/2010)
|
||||
|
||||
import libsaria
|
||||
from libsaria import callbacks
|
||||
exists = libsaria.path.exists
|
||||
expand = libsaria.path.expand
|
||||
|
||||
import library
|
||||
import playlist
|
||||
import queue
|
||||
import attrs
|
||||
|
||||
attrs.load_dattrs()
|
||||
cur_id = None
|
||||
|
||||
def get_cur_id():
|
||||
return cur_id
|
||||
|
||||
def inc_count():
|
||||
attrs.inc_count(get_cur_id())
|
||||
|
||||
def find_attrs(file, *attr_list):
|
||||
if file == None:
|
||||
return
|
||||
track = library.track.Track(file)
|
||||
if track == None:
|
||||
return
|
||||
id = library.update.song_id(file)
|
||||
get = track.__dict__.get
|
||||
res = []
|
||||
for attr in attr_list:
|
||||
if attr == "id":
|
||||
res.append(id)
|
||||
elif attr == "like":
|
||||
res.append(attrs.get_dattr(id, "like"))
|
||||
elif attr == "count":
|
||||
res.append(attrs.get_count(id))
|
||||
else:
|
||||
res.append(get(attr))
|
||||
return res
|
||||
|
||||
def find_all_attrs(file, attrs):
|
||||
if file == None:
|
||||
return False
|
||||
track = library.track.Track(file)
|
||||
if track == None:
|
||||
return False
|
||||
id = library.update.song_id(file)
|
||||
attrs.update(track.__dict__)
|
||||
attrs["id"] = id
|
||||
|
||||
# Function pointer to avoid unnecessary lookups for a common function
|
||||
get_attrs_id = library.get_attrs
|
||||
|
||||
def get_attrs(*attrs):
|
||||
# I should probably get a lock here...
|
||||
global cur_id
|
||||
res = None
|
||||
if cur_id:
|
||||
res = get_attrs_id(cur_id, *attrs)
|
||||
if res == None:
|
||||
cur_id = None
|
||||
file = libsaria.audio.get_cur_file()
|
||||
res = find_attrs(file, *attrs)
|
||||
if res == None:
|
||||
res = [None] * len(attrs)
|
||||
return res
|
||||
|
||||
def all_attrs():
|
||||
global cur_id
|
||||
res = {}
|
||||
found = False
|
||||
if cur_id:
|
||||
found = library.all_attrs(cur_id, res)
|
||||
if found == False:
|
||||
cur_id = None
|
||||
file = libsaria.audio.get_cur_file()
|
||||
found = find_all_attrs(file, res)
|
||||
if found != False:
|
||||
res["like"] = attrs.get_like(res["id"])
|
||||
res["count"] = attrs.get_count(res["id"])
|
||||
res["art"] = libsaria.path.lastfm.test_artwork(res)
|
||||
return res
|
||||
|
||||
def filter(text):
|
||||
visible = library.filter(text)
|
||||
playlist.set_visible(visible)
|
||||
queue.set_visible(visible)
|
||||
callbacks.refilter()
|
||||
|
||||
def is_visible(id):
|
||||
return library.is_visible(id)
|
||||
|
||||
def set_attr(attr, value):
|
||||
id = get_cur_id()
|
||||
if id:
|
||||
attrs.set_dattr(id, attr, value)
|
||||
|
||||
def make_library(path):
|
||||
path = expand(path)
|
||||
if not exists(path):
|
||||
return
|
||||
library.add_path(path)
|
||||
library.update_lib()
|
||||
|
||||
def play_id(id):
|
||||
global cur_id
|
||||
cur_id = id
|
||||
file = all_attrs()["filepath"]
|
||||
queue.rm_ids([id])
|
||||
libsaria.controls.load(file)
|
||||
libsaria.controls.play()
|
||||
|
||||
def next():
|
||||
global cur_id
|
||||
id = queue.next()
|
||||
if id == None:
|
||||
id = playlist.get_next(cur_id)
|
||||
if id != None:
|
||||
cur_id = id
|
||||
return all_attrs()["filepath"]
|
||||
|
||||
def list_source(list_func, *attrs):
|
||||
ret = []
|
||||
append = ret.append
|
||||
for id in list_func():
|
||||
append(get_attrs_id(id, *attrs))
|
||||
return ret
|
||||
|
||||
def list_library(*attrs):
|
||||
return list_source(library.list_ids, *attrs)
|
||||
|
||||
def list_playlist(*attrs):
|
||||
return list_source(playlist.list_ids, *attrs)
|
||||
|
||||
def list_queue(*attrs):
|
||||
return list_source(queue.list_ids, *attrs)
|
|
@ -1,50 +0,0 @@
|
|||
# Bryan Schumaker (5 / 28 / 2011)
|
||||
|
||||
import threading
|
||||
from libsaria import storage
|
||||
dattrs_lock = threading.Lock()
|
||||
lock_dattrs = dattrs_lock.acquire
|
||||
unlock_dattrs = dattrs_lock.release
|
||||
|
||||
# dynamic attributes
|
||||
dattrs = dict()
|
||||
|
||||
def load_dattrs():
|
||||
global dattrs
|
||||
dattrs_dict = storage.load_obj("dattrs", dict)
|
||||
lock_dattrs()
|
||||
dattrs = dattrs_dict
|
||||
unlock_dattrs()
|
||||
|
||||
def save_dattrs():
|
||||
storage.save_obj("dattrs", dattrs)
|
||||
|
||||
def get_dattr(id, attribute):
|
||||
lock_dattrs()
|
||||
attrs = dattrs.get(id, None)
|
||||
if attrs == None:
|
||||
unlock_dattrs()
|
||||
return None
|
||||
attr = attrs.get(attribute, None)
|
||||
unlock_dattrs()
|
||||
return attr
|
||||
|
||||
def set_dattr(id, attribute, value):
|
||||
lock_dattrs()
|
||||
attrs = dattrs.setdefault(id, dict())
|
||||
attrs[attribute] = value
|
||||
save_dattrs()
|
||||
unlock_dattrs()
|
||||
|
||||
def get_like(id):
|
||||
return get_dattr(id, "like")
|
||||
|
||||
def get_count(id):
|
||||
count = get_dattr(id, "count")
|
||||
if count != None:
|
||||
return count
|
||||
return 0
|
||||
|
||||
def inc_count(id):
|
||||
count = get_count(id)
|
||||
set_dattr(id, "count", count + 1)
|
|
@ -1,38 +0,0 @@
|
|||
# Bryan Schumaker (5 / 20 / 2011)
|
||||
|
||||
import libsaria
|
||||
import library
|
||||
import update
|
||||
import tree
|
||||
import index
|
||||
|
||||
# Function pointers for conveniance
|
||||
add_path = library.add_path
|
||||
list_paths = library.list_paths
|
||||
get_attrs = library.get_attrs
|
||||
all_attrs = library.all_attrs
|
||||
list_ids = tree.list_ids
|
||||
filter = index.filter
|
||||
is_visible = index.is_visible
|
||||
num_visible = index.num_visible
|
||||
|
||||
library.load()
|
||||
tree.make_tree()
|
||||
index.reindex()
|
||||
|
||||
def refresh():
|
||||
tree.make_tree()
|
||||
index.reindex()
|
||||
libsaria.callbacks.library_updated()
|
||||
|
||||
def update_lib():
|
||||
update.update()
|
||||
refresh()
|
||||
|
||||
def rm_path(path):
|
||||
library.rm_path(path)
|
||||
refresh()
|
||||
|
||||
def reset():
|
||||
library.reset()
|
||||
refresh()
|
|
@ -1,86 +0,0 @@
|
|||
# Bryan Schumaker (5 / 21 / 2011)
|
||||
|
||||
import re
|
||||
import string
|
||||
import library
|
||||
|
||||
lib_index = dict()
|
||||
all_ids = set()
|
||||
matching = set()
|
||||
search = re.search
|
||||
|
||||
space_ord = ord(" ")
|
||||
stripc = u"\"#$%&'*+<=>@[]^`{|}~.?!"
|
||||
splitc = u"-\/,:;()_~+"
|
||||
upper = string.uppercase
|
||||
lower = string.lowercase
|
||||
|
||||
# Create a translation table for formatting text
|
||||
ttable = dict((ord(c), None) for c in stripc)
|
||||
splitt = dict((ord(c), space_ord) for c in splitc)
|
||||
lowert = dict((ord(c), ord(lower[i])) for i, c in enumerate(upper))
|
||||
for t in (splitt, lowert):
|
||||
for c in t:
|
||||
ttable[c] = t[c]
|
||||
|
||||
def reset():
|
||||
global lib_index
|
||||
global all_ids
|
||||
lib_index = dict()
|
||||
all_ids = set()
|
||||
|
||||
def format(text):
|
||||
return text.translate(ttable).split()
|
||||
|
||||
def add_to_index(id, text):
|
||||
for word in format(text):
|
||||
if lib_index.get(word) == None:
|
||||
lib_index[word] = set([id])
|
||||
else:
|
||||
lib_index[word].add(id)
|
||||
|
||||
def add_tracks(tracks):
|
||||
for id, track in tracks.iteritems():
|
||||
all_ids.add(id)
|
||||
add_to_index(id, track.artist)
|
||||
add_to_index(id, track.album)
|
||||
add_to_index(id, track.title)
|
||||
|
||||
def reindex():
|
||||
global matching
|
||||
reset()
|
||||
for src, tracks in library.lib_dict.iteritems():
|
||||
add_tracks(tracks)
|
||||
matching = all_ids
|
||||
|
||||
def is_visible(id):
|
||||
return id in matching
|
||||
|
||||
def num_visible():
|
||||
return len(matching)
|
||||
|
||||
def do_filter(terms):
|
||||
if len(terms) == 0:
|
||||
return all_ids
|
||||
|
||||
get = lib_index.get
|
||||
results = dict((t, set()) for t in terms)
|
||||
for key in lib_index.keys():
|
||||
for term in terms:
|
||||
if search(term, key):
|
||||
results[term].update(get(key))
|
||||
|
||||
visible = set()
|
||||
for i, t in enumerate(terms):
|
||||
if i == 0:
|
||||
visible.update(results[t])
|
||||
else:
|
||||
visible.intersection_update(results[t])
|
||||
return visible
|
||||
|
||||
def filter(text):
|
||||
global matching
|
||||
text = unicode(text)
|
||||
terms = format(text)
|
||||
matching = do_filter(terms)
|
||||
return matching
|
|
@ -1,100 +0,0 @@
|
|||
# Bryan Schumaker (5 / 20 / 2011)
|
||||
|
||||
import threading
|
||||
from libsaria import storage
|
||||
from libsaria.sources import attrs
|
||||
|
||||
library_lock = threading.Lock()
|
||||
lock_library = library_lock.acquire
|
||||
unlock_library = library_lock.release
|
||||
get_dattr = attrs.get_dattr
|
||||
get_count = attrs.get_count
|
||||
|
||||
# Map directory -> dict()
|
||||
lib_dict = None
|
||||
LIB_FILE = "library"
|
||||
|
||||
def load():
|
||||
global lib_dict
|
||||
saved_lib = storage.load_obj(LIB_FILE, dict)
|
||||
if saved_lib.__class__ != dict:
|
||||
saved_lib = dict()
|
||||
lock_library()
|
||||
lib_dict = saved_lib
|
||||
unlock_library()
|
||||
|
||||
# NOTE: You should already be holding the lock when you call this
|
||||
def save():
|
||||
storage.save_obj(LIB_FILE, lib_dict)
|
||||
|
||||
def reset():
|
||||
global lib_dict
|
||||
lock_library()
|
||||
lib_dict = {}
|
||||
save()
|
||||
unlock_library()
|
||||
|
||||
def add_path(path):
|
||||
lock_library()
|
||||
lib_dict.setdefault(path, dict())
|
||||
unlock_library()
|
||||
|
||||
def rm_path(path):
|
||||
lock_library()
|
||||
del lib_dict[path]
|
||||
save()
|
||||
unlock_library()
|
||||
|
||||
def list_paths():
|
||||
res = []
|
||||
lock_library()
|
||||
for path, lib in lib_dict.iteritems():
|
||||
res.append((path, lib))
|
||||
unlock_library()
|
||||
return res
|
||||
|
||||
def find_id(id):
|
||||
for src, tracks in lib_dict.iteritems():
|
||||
track = tracks.get(id, None)
|
||||
if track != None:
|
||||
return track
|
||||
|
||||
def size():
|
||||
res = 0
|
||||
lock_library()
|
||||
for src, tracks in lib_dict.iteritems():
|
||||
res += len(tracks)
|
||||
unlock_library()
|
||||
return res
|
||||
|
||||
def get_attrs(id, *attrs):
|
||||
lock_library()
|
||||
track = find_id(id)
|
||||
if track == None:
|
||||
unlock_library()
|
||||
return None
|
||||
|
||||
get = track.__dict__.get
|
||||
res = []
|
||||
for attr in attrs:
|
||||
if attr == "id":
|
||||
res.append(id)
|
||||
elif attr == "like":
|
||||
res.append(get_dattr(id, attr))
|
||||
elif attr == "count":
|
||||
res.append(get_count(id))
|
||||
else:
|
||||
res.append(get(attr))
|
||||
unlock_library()
|
||||
return res
|
||||
|
||||
def all_attrs(id, attrs):
|
||||
lock_library()
|
||||
found = False
|
||||
track = find_id(id)
|
||||
if track != None:
|
||||
attrs.update(track.__dict__)
|
||||
attrs["id"] = id
|
||||
found = True
|
||||
unlock_library()
|
||||
return found
|
|
@ -1,28 +0,0 @@
|
|||
# Bryan Schumaker (5 / 21 / 2011)
|
||||
|
||||
import tagpy
|
||||
import datetime
|
||||
|
||||
FileRef = tagpy.FileRef
|
||||
timedelta = datetime.timedelta
|
||||
|
||||
class Track:
|
||||
def __init__(self, filepath):
|
||||
ref = FileRef(filepath)
|
||||
tags = ref.tag()
|
||||
audio = ref.audioProperties()
|
||||
|
||||
self.artist = tags.artist or u"Unknown Artist"
|
||||
self.album = tags.album or u"Unknown Album"
|
||||
self.title = tags.title or u"Unknown Title"
|
||||
self.track = tags.track
|
||||
self.genre = tags.genre
|
||||
self.year = tags.year
|
||||
self.seconds = audio.length
|
||||
self.filepath = filepath
|
||||
|
||||
lenstr = "%s" % timedelta(seconds=self.seconds)
|
||||
if lenstr[:2] == "0:":
|
||||
self.lenstr = lenstr[2:]
|
||||
else:
|
||||
self.lenstr = lenstr
|
|
@ -1,57 +0,0 @@
|
|||
# Bryan Schumaker (2 / 12 / 2011)
|
||||
|
||||
import string
|
||||
import library
|
||||
ttable = dict()
|
||||
for s in string.punctuation:
|
||||
ttable[ord(s)] = u""
|
||||
for s in string.lowercase:
|
||||
ttable[ord(s)] = ord(s) - 32
|
||||
|
||||
class Tree(dict):
|
||||
def __init__(self):
|
||||
dict.__init__(self)
|
||||
|
||||
def walk(self):
|
||||
keys = self.keys()
|
||||
keys.sort()
|
||||
|
||||
for key in keys:
|
||||
child = self[key]
|
||||
if len(child.keys()) == 0:
|
||||
yield key
|
||||
continue
|
||||
for res in child.walk():
|
||||
yield res
|
||||
|
||||
def __insert__(self, path):
|
||||
path_part = path[0]
|
||||
child = self.get(path_part, None)
|
||||
if child == None:
|
||||
child = self.__class__()
|
||||
self[path_part] = child
|
||||
return child
|
||||
|
||||
def insert(self, path):
|
||||
child = self.__insert__(path)
|
||||
if len(path) > 1:
|
||||
child.insert(path[1:])
|
||||
|
||||
|
||||
lib_tree = None
|
||||
|
||||
def list_ids():
|
||||
for id in lib_tree.walk():
|
||||
yield id
|
||||
|
||||
def add_tracks(tracks):
|
||||
for id, track in tracks.iteritems():
|
||||
artist = track.artist.translate(ttable)
|
||||
album = track.album.translate(ttable)
|
||||
lib_tree.insert([artist, album, track.track, id])
|
||||
|
||||
def make_tree():
|
||||
global lib_tree
|
||||
lib_tree = Tree()
|
||||
for src, tracks in library.lib_dict.iteritems():
|
||||
add_tracks(tracks)
|
|
@ -1,54 +0,0 @@
|
|||
# Bryan Schumaker (5 / 21 / 2011)
|
||||
|
||||
import os
|
||||
|
||||
import library
|
||||
import track
|
||||
|
||||
stat = os.stat
|
||||
walk = os.walk
|
||||
join = os.path.join
|
||||
|
||||
Track = track.Track
|
||||
|
||||
def song_id(path):
|
||||
return stat(path).st_ino
|
||||
|
||||
def scan_path(path):
|
||||
file_map = dict()
|
||||
for root, dir, files in walk(path):
|
||||
for file in files:
|
||||
file = join(root, file)
|
||||
file_map[song_id(file)] = file
|
||||
return file_map
|
||||
|
||||
def rm_old_ids(old_ids, new_ids, tracks):
|
||||
to_remove = old_ids - new_ids
|
||||
for id in to_remove:
|
||||
del tracks[id]
|
||||
|
||||
def add_new_ids(old_ids, new_ids, tracks, file_map):
|
||||
to_add = new_ids - old_ids
|
||||
for id in to_add:
|
||||
try:
|
||||
fpath = file_map[id]
|
||||
tracks[id] = Track(fpath)
|
||||
except Exception, e:
|
||||
pass
|
||||
|
||||
def update_path(path, tracks):
|
||||
file_map = scan_path(path)
|
||||
old_ids = set(tracks.keys())
|
||||
new_ids = set(file_map.keys())
|
||||
|
||||
rm_old_ids(old_ids, new_ids, tracks)
|
||||
add_new_ids(old_ids, new_ids, tracks, file_map)
|
||||
|
||||
def update():
|
||||
library.lock_library()
|
||||
for path, lib in library.lib_dict.iteritems():
|
||||
print "Updating path:", path
|
||||
update_path(path, lib)
|
||||
print "Done!"
|
||||
library.save()
|
||||
library.unlock_library()
|
|
@ -1,51 +0,0 @@
|
|||
# Bryan Schumaker (11/07/2010)
|
||||
|
||||
import libsaria
|
||||
import playlist
|
||||
import next
|
||||
|
||||
# Function pointers for convenience
|
||||
add_ids = playlist.add_ids
|
||||
|
||||
playlist.load()
|
||||
visible = playlist.as_set()
|
||||
|
||||
def add_ids(ids):
|
||||
for id in ids:
|
||||
if libsaria.sources.is_visible(id):
|
||||
visible.add(id)
|
||||
playlist.add_ids(ids)
|
||||
|
||||
def rm_ids(ids):
|
||||
global visible
|
||||
visible = visible - set(ids)
|
||||
playlist.rm_ids(ids)
|
||||
|
||||
def reset():
|
||||
global visible
|
||||
visible = set()
|
||||
playlist.reset()
|
||||
|
||||
def list_ids():
|
||||
for id in playlist.song_list:
|
||||
yield id
|
||||
|
||||
def set_visible(vset):
|
||||
global visible
|
||||
visible = playlist.as_set().intersection(vset)
|
||||
|
||||
def num_visible():
|
||||
return len(visible)
|
||||
|
||||
def get_next(cur_id):
|
||||
id = None
|
||||
if libsaria.prefs.get("libsaria.random") == True:
|
||||
index = next.rand_next(list(visible))
|
||||
else:
|
||||
index = next.seq_next(cur_id)
|
||||
if index != None:
|
||||
id = playlist.get(index)
|
||||
if id != None:
|
||||
artist, title = libsaria.sources.get_attrs_id(id, "artist", "title")
|
||||
next.track_recent(artist, title)
|
||||
return id
|
|
@ -1,50 +0,0 @@
|
|||
# Bryan Schumaker (5 / 14 / 2011)
|
||||
|
||||
import random
|
||||
import playlist
|
||||
import libsaria
|
||||
|
||||
recent = []
|
||||
|
||||
def track_recent(artist, title):
|
||||
recent.append((artist, title))
|
||||
if len(recent) > 50:
|
||||
recent.pop(0)
|
||||
|
||||
def incr_index(cur_index, max_index):
|
||||
cur_index += 1
|
||||
if cur_index == max_index:
|
||||
cur_index = 0
|
||||
return cur_index
|
||||
|
||||
def seq_next(cur_id):
|
||||
is_visible = libsaria.sources.is_visible
|
||||
|
||||
max = playlist.size()
|
||||
if max == 0: # List is empty
|
||||
return
|
||||
|
||||
index = playlist.index(cur_id)
|
||||
index = incr_index(index, max)
|
||||
while not is_visible(playlist.get(index)):
|
||||
index = incr_index(index, max)
|
||||
return index
|
||||
|
||||
def check_candidate(id):
|
||||
(artist, title, like) = libsaria.sources.get_attrs_id(id, "artist", "title", "like")
|
||||
if (artist, title) in recent:
|
||||
return False
|
||||
if like == False:
|
||||
return False
|
||||
return True
|
||||
|
||||
def rand_next(list):
|
||||
max = len(list) - 1
|
||||
if max == -1: # List is empty
|
||||
return
|
||||
for i in xrange(15):
|
||||
index = random.randint(0, max)
|
||||
id = list[index]
|
||||
if check_candidate(id) == True:
|
||||
break
|
||||
return playlist.index(id)
|
|
@ -1,77 +0,0 @@
|
|||
# Bryan Schumaker (5 / 11 / 2011)
|
||||
# TODO: Split this file into two files, similiar to how audio is broken up
|
||||
|
||||
import threading
|
||||
from libsaria import storage
|
||||
plist_lock = threading.Lock()
|
||||
lock_plist = plist_lock.acquire
|
||||
unlock_plist = plist_lock.release
|
||||
|
||||
# Playlist
|
||||
song_list = []
|
||||
song_set = set()
|
||||
|
||||
def load():
|
||||
global song_list
|
||||
plist_list = storage.load_obj("playlist", list)
|
||||
# TODO: Can I do this check during load_obj???
|
||||
if plist_list.__class__ != list:
|
||||
plist_list = []
|
||||
lock_plist()
|
||||
song_list = plist_list
|
||||
unlock_plist()
|
||||
|
||||
# NOTE: You should already be holding the lock when you call this
|
||||
def save():
|
||||
storage.save_obj("playlist", song_list)
|
||||
|
||||
def reset():
|
||||
global song_list
|
||||
lock_plist()
|
||||
song_list = []
|
||||
save()
|
||||
unlock_plist()
|
||||
|
||||
def add_ids(id_list):
|
||||
lock_plist()
|
||||
song_list.extend(id_list)
|
||||
save()
|
||||
unlock_plist()
|
||||
|
||||
def rm_ids(id_list):
|
||||
lock_plist()
|
||||
for id in id_list:
|
||||
if id in song_list:
|
||||
song_list.remove(id)
|
||||
save()
|
||||
unlock_plist()
|
||||
|
||||
def as_set():
|
||||
lock_plist()
|
||||
song_set = set(song_list)
|
||||
unlock_plist()
|
||||
return song_set
|
||||
|
||||
def size():
|
||||
lock_plist()
|
||||
sz = len(song_list)
|
||||
unlock_plist()
|
||||
return sz
|
||||
|
||||
def index(item):
|
||||
lock_plist()
|
||||
try:
|
||||
idx = song_list.index(item)
|
||||
except:
|
||||
idx = -1
|
||||
unlock_plist()
|
||||
return idx
|
||||
|
||||
def get(index):
|
||||
lock_plist()
|
||||
try:
|
||||
item = song_list[index]
|
||||
except:
|
||||
item = None
|
||||
unlock_plist()
|
||||
return item
|
|
@ -1,42 +0,0 @@
|
|||
# Bryan Schumaker (12/12/2010)
|
||||
|
||||
import libsaria
|
||||
from libsaria import callbacks
|
||||
import queue
|
||||
|
||||
visible = set()
|
||||
|
||||
def rm_ids(ids):
|
||||
global visible
|
||||
visible = visible - set(ids)
|
||||
queue.rm_ids(ids)
|
||||
|
||||
def reset():
|
||||
global visible
|
||||
visible = set()
|
||||
queue.reset()
|
||||
|
||||
def list_ids():
|
||||
for id in queue.queue_list:
|
||||
yield id
|
||||
|
||||
def add_ids(id_list):
|
||||
queue.add_ids(id_list)
|
||||
for id in id_list:
|
||||
if libsaria.sources.is_visible(id):
|
||||
visible.add(id)
|
||||
callbacks.queue_changed()
|
||||
|
||||
def set_visible(vset):
|
||||
global visible
|
||||
visible = queue.as_set().intersection(vset)
|
||||
|
||||
def num_visible():
|
||||
return len(visible)
|
||||
|
||||
def next():
|
||||
id = queue.pop()
|
||||
if id != None:
|
||||
visible.remove(id)
|
||||
return id
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
# Bryan Schumaker (5 / 7 / 2011)
|
||||
|
||||
import threading
|
||||
from libsaria import callbacks
|
||||
queue_lock = threading.Lock()
|
||||
lock_queue = queue_lock.acquire
|
||||
unlock_queue = queue_lock.release
|
||||
|
||||
# List of queued songs
|
||||
queue_list = []
|
||||
|
||||
def add_ids(id_list):
|
||||
lock_queue()
|
||||
queue_list.extend(id_list)
|
||||
unlock_queue()
|
||||
|
||||
def rm_ids(id_list):
|
||||
lock_queue()
|
||||
for id in id_list:
|
||||
if id in queue_list:
|
||||
queue_list.remove(id)
|
||||
unlock_queue()
|
||||
callbacks.queue_changed()
|
||||
|
||||
def pop():
|
||||
lock_queue()
|
||||
id = None
|
||||
if len(queue_list) > 0:
|
||||
id = queue_list.pop(0)
|
||||
unlock_queue()
|
||||
callbacks.queue_changed()
|
||||
return id
|
||||
|
||||
def reset():
|
||||
global queue_list
|
||||
lock_queue()
|
||||
queue_list = []
|
||||
unlock_queue()
|
||||
|
||||
def as_set():
|
||||
lock_queue()
|
||||
song_set = set(queue_list)
|
||||
unlock_queue()
|
||||
return song_set
|
|
@ -1,39 +0,0 @@
|
|||
# Bryan Schumaker (4 / 28 / 2011)
|
||||
|
||||
import os
|
||||
from os import path
|
||||
import cPickle as pickle
|
||||
from libsaria import version
|
||||
import cache
|
||||
|
||||
USER_DIR = path.expanduser("~")
|
||||
PROTO = pickle.HIGHEST_PROTOCOL
|
||||
|
||||
saria = ".saria"
|
||||
if version.__dev__ == True:
|
||||
saria = ".saria-dev"
|
||||
SARIA_DIR = path.join(USER_DIR, saria)
|
||||
if path.exists(SARIA_DIR) == False:
|
||||
os.mkdir(SARIA_DIR)
|
||||
cache.set_basedir(SARIA_DIR)
|
||||
|
||||
def full_path(filename):
|
||||
return path.join(SARIA_DIR, filename)
|
||||
|
||||
def save_obj(filename, object):
|
||||
f = open(full_path(filename), 'w')
|
||||
p = pickle.Pickler(f, PROTO)
|
||||
p.dump(object)
|
||||
f.close()
|
||||
|
||||
def load_obj(filename, default):
|
||||
file = full_path(filename)
|
||||
if path.exists(file) == False:
|
||||
return default()
|
||||
f = open(file)
|
||||
try:
|
||||
object = pickle.loads(f.read())
|
||||
except:
|
||||
object = default()
|
||||
f.close()
|
||||
return object
|
|
@ -1,59 +0,0 @@
|
|||
# Bryan Schumaker (5 / 6 / 2011)
|
||||
|
||||
import os
|
||||
join = os.path.join
|
||||
sep = os.path.sep
|
||||
isfile = os.path.isfile
|
||||
isdir = os.path.isdir
|
||||
getsize = os.path.getsize
|
||||
CACHE_DIR = None
|
||||
|
||||
def set_basedir(saria_dir):
|
||||
global CACHE_DIR
|
||||
CACHE_DIR = join(saria_dir, "cache")
|
||||
|
||||
def file_exists(cache_path):
|
||||
if not isfile(cache_path):
|
||||
return False
|
||||
return getsize(cache_path) != 0
|
||||
|
||||
def make_cache_path(artist, album, file):
|
||||
cache_file = "%s%s%s%s" % (artist, sep, album, sep)
|
||||
cache_path = join(CACHE_DIR, cache_file)
|
||||
if not isdir(cache_path):
|
||||
os.makedirs(cache_path)
|
||||
return join(cache_path, file)
|
||||
|
||||
def fill_cache(artist, album, title, cache_func, cache_path):
|
||||
text = cache_func(artist, album, title)
|
||||
if text != None:
|
||||
try:
|
||||
f = open(cache_path, 'w')
|
||||
f.write(text)
|
||||
f.close()
|
||||
except:
|
||||
pass
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_item(artist, album, title, file, cache_func, default):
|
||||
cache_path = make_cache_path(artist, album, file)
|
||||
filled = True
|
||||
if not file_exists(cache_path):
|
||||
filled = fill_cache(artist, album, title, cache_func, cache_path)
|
||||
if filled == False:
|
||||
return default
|
||||
return cache_path
|
||||
|
||||
def test_item(artist, album, file, default):
|
||||
cache_path = make_cache_path(artist, album, file)
|
||||
if not file_exists(cache_path):
|
||||
return default
|
||||
return cache_path
|
||||
|
||||
def copy_in_file(artist, album, file, orig_file):
|
||||
cache_path = make_cache_path(artist, album, file)
|
||||
orig = open(orig_file)
|
||||
f = open(cache_path, 'w')
|
||||
f.write(orig.read())
|
||||
f.close()
|
|
@ -1,192 +0,0 @@
|
|||
# Bryan Schumaker (11/06/2010)
|
||||
|
||||
from libsaria.path import files
|
||||
from libsaria.path import sep
|
||||
|
||||
class Tree(dict):
|
||||
def __init__(self):
|
||||
dict.__init__(self)
|
||||
|
||||
def __len__(self):
|
||||
count = 0;
|
||||
for path in self.walk():
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def __disp__(self, child, level):
|
||||
return "%s", child
|
||||
|
||||
def disp(self, level = 0):
|
||||
for child in self:
|
||||
space = " " * level
|
||||
fmt, vals = self.__disp__(child, level)
|
||||
print space, fmt % vals
|
||||
self[child].disp(level + 1)
|
||||
|
||||
def walk(self):
|
||||
keys = self.keys()
|
||||
keys.sort()
|
||||
|
||||
for key in keys:
|
||||
child = self[key]
|
||||
if len(child.keys()) == 0:
|
||||
yield [key]
|
||||
continue
|
||||
for res in child.walk():
|
||||
yield [key] + res
|
||||
|
||||
def __insert__(self, path):
|
||||
path_part = path[0]
|
||||
child = self.get(path_part, None)
|
||||
if child == None:
|
||||
child = self.__class__()
|
||||
self[path_part] = child
|
||||
return child
|
||||
|
||||
def insert(self, path):
|
||||
child = self.__insert__(path)
|
||||
if len(path) > 1:
|
||||
child.insert(path[1:])
|
||||
|
||||
def lookup(self, path):
|
||||
child = self.get(path[0], None)
|
||||
if child == None:
|
||||
return child
|
||||
if len(path) > 1:
|
||||
return child.lookup(path[1:])
|
||||
return child.keys()
|
||||
|
||||
def lookup_child(self, path):
|
||||
child = self.get(path[0], None)
|
||||
if child == None:
|
||||
return child
|
||||
if len(path) > 1:
|
||||
return child.lookup_child(path[1:])
|
||||
return child
|
||||
|
||||
|
||||
class DLTree(Tree):
|
||||
def __init__(self):
|
||||
Tree.__init__(self)
|
||||
self.parent = None
|
||||
|
||||
def walk_backwards(self, child = None):
|
||||
key = None
|
||||
if child != None:
|
||||
idc = id(child)
|
||||
key = [i[0] for i in self.items() if id(i[1]) == idc]
|
||||
if self.parent == None:
|
||||
return key
|
||||
ret = self.parent.walk_backwards(self)
|
||||
if key:
|
||||
return ret + key
|
||||
else:
|
||||
return ret
|
||||
|
||||
def insert(self, path):
|
||||
child = self.__insert__(path)
|
||||
child.parent = self
|
||||
if len(path) > 1:
|
||||
return child.insert(path[1:])
|
||||
return child
|
||||
|
||||
|
||||
class FSTree(Tree):
|
||||
def __init__(self):
|
||||
Tree.__init__(self)
|
||||
|
||||
def walk_paths(self):
|
||||
for path in self.walk():
|
||||
yield sep.join(path)
|
||||
|
||||
def insert_path(self, base, file = None):
|
||||
path = base.split(sep)
|
||||
self.insert_path_split(path, file)
|
||||
|
||||
def insert_path_split(self, base, file = None):
|
||||
if file == None:
|
||||
self.insert(base)
|
||||
else:
|
||||
self.insert(base + [file])
|
||||
|
||||
|
||||
class DLFSTree(DLTree, FSTree):
|
||||
def __init__(self):
|
||||
DLTree.__init__(self)
|
||||
FSTree.__init__(self)
|
||||
|
||||
def walk_path_backwards(self):
|
||||
return sep.join( self.walk_backwards() )
|
||||
|
||||
def insert_path(self, base, file = None):
|
||||
path = base.split(sep)
|
||||
return self.insert_path_split(path, file)
|
||||
|
||||
def insert_path_split(self, base, file = None):
|
||||
if file == None:
|
||||
child = self.insert(base)
|
||||
else:
|
||||
child = self.insert(base + [file])
|
||||
return child
|
||||
|
||||
|
||||
class ValTree(Tree):
|
||||
def __init__(self):
|
||||
Tree.__init__(self)
|
||||
self.value = None
|
||||
|
||||
def __disp__(self, child, level):
|
||||
return "%s (%s)", (child, self[child].value)
|
||||
|
||||
def __walk_vals__(self, path):
|
||||
node = self
|
||||
res = []
|
||||
for key in path:
|
||||
node = node[key]
|
||||
res.append(node.value)
|
||||
return res
|
||||
|
||||
def walk_vals(self):
|
||||
for path in self.walk():
|
||||
yield self.__walk_vals__(path)
|
||||
|
||||
def insert(self, path, values):
|
||||
child = self.__insert__(path)
|
||||
if len(values) > 0:
|
||||
child.value = values[0]
|
||||
vals = values[1:]
|
||||
else:
|
||||
vals = values
|
||||
if len(path) > 1:
|
||||
child.insert(path[1:], values[1:])
|
||||
|
||||
|
||||
class DLValTree(DLTree, ValTree):
|
||||
def __init__(self):
|
||||
DLTree.__init__(self)
|
||||
ValTree.__init__(self)
|
||||
|
||||
def walk_vals_backwards(self, child = None):
|
||||
key = None
|
||||
if child != None:
|
||||
idc = id(child)
|
||||
key = [i[0] for i in self.items() if id(i[1]) == idc]
|
||||
if self.parent == None:
|
||||
return [self[key[0]].value]
|
||||
ret = self.parent.walk_vals_backwards(self)
|
||||
if key:
|
||||
return ret + [self[key[0]].value]
|
||||
else:
|
||||
return ret
|
||||
|
||||
def insert(self, path, values):
|
||||
child = self.__insert__(path)
|
||||
child.parent = self
|
||||
if len(values) > 0:
|
||||
child.value = values[0]
|
||||
vals = values[1:]
|
||||
else:
|
||||
vals = values
|
||||
if len(path) > 1:
|
||||
return child.insert(path[1:], vals)
|
||||
return child
|
|
@ -1,13 +0,0 @@
|
|||
# Bryan Schumaker (5 / 6 / 2011)
|
||||
|
||||
__major__ = 4
|
||||
__minor__ = 9
|
||||
__bug__ = 0
|
||||
__dev__ = False
|
||||
|
||||
__vstr__ = "%s.%s" % (__major__, __minor__)
|
||||
if __bug__ > 0:
|
||||
__vstr__ = "%s.%s" % (__vstr__, __bug__)
|
||||
if __dev__ == True:
|
||||
__vstr__ += "-dev"
|
||||
__vers__ = "Libsaria %s" % __vstr__
|
|
@ -1,38 +0,0 @@
|
|||
# Bryan Schumaker (10/24/2010)
|
||||
|
||||
from libsaria import version
|
||||
import urllib2
|
||||
import string
|
||||
|
||||
HEADER = version.__vers__
|
||||
|
||||
#vals = [ ('%','25'), (' ','20'), ('&','26'), ('<','3C'), ('>','3E'),
|
||||
# ('"','22'), ('#','23'), ('$','24'), ('+', '2B'), ('\'','27'), #('+','2B'),
|
||||
# (',','2C'), ('/','2F'), (':','3A'), ('[','5B'), (']','5D')]
|
||||
vals = [ (' ','20'), ('&','26'), ('\'', '27') ]
|
||||
|
||||
|
||||
class Url:
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
value = escape(value)
|
||||
self.url += "&" + key + "=" + value
|
||||
|
||||
def open(self):
|
||||
print self.url
|
||||
try:
|
||||
req = urllib2.Request(self.url)
|
||||
req.add_header('User-Agent', HEADER)
|
||||
return urllib2.urlopen(req)
|
||||
except Exception, e:
|
||||
print e
|
||||
return None
|
||||
|
||||
|
||||
def escape(string):
|
||||
for l in vals:
|
||||
string = string.replace(l[0], "%s%s" % ('%', l[1]))
|
||||
return string
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
# Bryan Schumaker (10/24/2010)
|
||||
|
||||
import xml.dom.minidom as xml
|
||||
|
||||
def attributes(node):
|
||||
attrs = dict()
|
||||
for i in range(node.attributes.length):
|
||||
item = node.attributes.item(i)
|
||||
attrs[item.name] = item.nodeValue
|
||||
return attrs
|
||||
|
||||
def children(doc):
|
||||
list = []
|
||||
for node in doc.childNodes:
|
||||
if node.nodeType == node.TEXT_NODE:
|
||||
if node.data.strip() == "":
|
||||
continue
|
||||
list += [node]
|
||||
return list
|
||||
|
||||
def child(doc):
|
||||
list = children(doc)
|
||||
if len(list) > 0:
|
||||
return list[0]
|
||||
return None
|
||||
|
||||
def check_type(value):
|
||||
if value.__class__ == unicode:
|
||||
return value.encode("utf-8")
|
||||
return str(value)
|
||||
|
||||
def add_child(doc, node, name, attrs = {}):
|
||||
child = doc.createElement(name)
|
||||
for attr in attrs:
|
||||
value = check_type(attrs[attr])
|
||||
child.setAttribute(attr, value)
|
||||
node.appendChild(child)
|
||||
return child
|
||||
|
||||
def add_text(doc, node, value):
|
||||
value = check_type(value)
|
||||
try:
|
||||
child = doc.createTextNode( value )
|
||||
node.appendChild(child)
|
||||
return value
|
||||
except Exception, e:
|
||||
print e
|
||||
print value, value.__class__
|
||||
|
||||
def get_elements(doc, tag):
|
||||
return doc.getElementsByTagName(tag)
|
||||
|
||||
def find_attribute(doc, tag, attr, value):
|
||||
for node in get_elements(doc, tag):
|
||||
if attributes(node)[attr] == value:
|
||||
return node
|
||||
return None
|
||||
|
||||
def find_preferred_attribute(doc, tag, attr, values):
|
||||
for value in values:
|
||||
attr = find_attribute(doc, tag, attr, value)
|
||||
if attr:
|
||||
return attr
|
||||
None
|
||||
|
||||
def new():
|
||||
return xml.Document()
|
||||
|
||||
def parse(xml_file):
|
||||
return xml.parse(xml_file)
|
|
@ -1,34 +0,0 @@
|
|||
# Bryan Schumaker (8/13/2010)
|
||||
|
||||
import datetime
|
||||
now = datetime.datetime.now
|
||||
__start__ = now()
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
gobject.threads_init()
|
||||
|
||||
import libsaria
|
||||
__vers__ = "Ocarina %s" % libsaria.version.__vstr__
|
||||
|
||||
def uptime():
|
||||
return now() - __start__
|
||||
|
||||
def quit(window, event):
|
||||
gtk.main_quit()
|
||||
libsaria.shutdown()
|
||||
print "Ocarina ran for:", uptime()
|
||||
|
||||
import window
|
||||
import playlist
|
||||
import queue
|
||||
import library
|
||||
import settings
|
||||
import callbacks
|
||||
|
||||
def run():
|
||||
import body
|
||||
body.footer.set_art("images/ocarina.png")
|
||||
libsaria.startup()
|
||||
print "Startup took:", uptime()
|
||||
gtk.main()
|
|
@ -1,62 +0,0 @@
|
|||
# Bryan Schumaker (11/24/2010)
|
||||
|
||||
import gtk
|
||||
from page import OcarinaPage
|
||||
from ocarina import shortcuts
|
||||
|
||||
body = gtk.Notebook()
|
||||
body.show()
|
||||
body.set_tab_pos(gtk.POS_LEFT)
|
||||
page_num = body.page_num
|
||||
|
||||
def add_page(content, page_name):
|
||||
label = gtk.Label(page_name)
|
||||
label.set_angle(90)
|
||||
page = OcarinaPage(content, label)
|
||||
body.append_page(page, label)
|
||||
body.set_tab_label_packing(page, True, True, gtk.PACK_START)
|
||||
n = body.get_n_pages()
|
||||
if n == 1:
|
||||
page.visible()
|
||||
elif n == 2:
|
||||
body.connect("switch-page", switch_page)
|
||||
return page
|
||||
|
||||
def remove_page(page):
|
||||
page.invisible()
|
||||
page.rm_content()
|
||||
body.remove_page(page_num(page))
|
||||
|
||||
def current_page():
|
||||
cur_num = body.get_current_page()
|
||||
return body.get_nth_page(cur_num)
|
||||
|
||||
def switch_to_page_n(n):
|
||||
body.set_current_page(n)
|
||||
|
||||
def switch_to_page(page):
|
||||
switch_to_page_n(page_num(page))
|
||||
|
||||
def switch_page(notebook, page, pagenum):
|
||||
cur_pg = current_page()
|
||||
next_pg = body.get_nth_page(pagenum)
|
||||
cur_pg.invisible()
|
||||
next_pg.visible()
|
||||
|
||||
def hide_page(page):
|
||||
n = page_num(page)
|
||||
if n > 0:
|
||||
switch_to_page_n(n - 1)
|
||||
page.hide()
|
||||
|
||||
def show_page(page, switch = False):
|
||||
page.show()
|
||||
if switch == True:
|
||||
switch_to_page(page)
|
||||
|
||||
def cur_page_goto():
|
||||
current_page().goto()
|
||||
shortcuts.register_shortcut("g", cur_page_goto)
|
||||
|
||||
def cur_page_clear():
|
||||
current_page().clear()
|
|
@ -1,161 +0,0 @@
|
|||
# Bryan Schumaker (2 / 20 / 2011)
|
||||
|
||||
import gtk
|
||||
from libsaria.path import files
|
||||
from libsaria import controls
|
||||
from libsaria import sources
|
||||
from ocarina import fsselect
|
||||
|
||||
SIZE = gtk.ICON_SIZE_MENU
|
||||
|
||||
def on_click(button, func):
|
||||
func()
|
||||
|
||||
def on_toggle(button, func):
|
||||
func(button.get_active())
|
||||
|
||||
def stock_image(stock_item):
|
||||
img = gtk.image_new_from_stock(stock_item, SIZE)
|
||||
return img
|
||||
|
||||
def file_image(file):
|
||||
img = gtk.image_new_from_file(file)
|
||||
return img
|
||||
|
||||
def make_text(text):
|
||||
lbl = gtk.Label(text)
|
||||
lbl.show()
|
||||
return lbl
|
||||
|
||||
def default_button_attrs(button, img, tooltip, show):
|
||||
button.set_relief(gtk.RELIEF_NONE)
|
||||
if img != None:
|
||||
img.show()
|
||||
button.add(img)
|
||||
if tooltip != None:
|
||||
button.set_tooltip_text(tooltip)
|
||||
if show == True:
|
||||
button.show()
|
||||
|
||||
def make_button(stock_item, func, tooltip, show):
|
||||
b = gtk.Button()
|
||||
b.connect("clicked", on_click, func)
|
||||
default_button_attrs(b, stock_image(stock_item), tooltip, show)
|
||||
return b
|
||||
|
||||
def toggle_connect(button, func):
|
||||
button.t_id = button.connect("toggled", on_toggle, func)
|
||||
button.t_func = func
|
||||
|
||||
def toggle_call_unconnected(button, func, *args):
|
||||
button.disconnect(button.t_id)
|
||||
func(*args)
|
||||
toggle_connect(button, button.t_func)
|
||||
|
||||
def make_toggle(img_file, func, tooltip, is_active, show):
|
||||
b = gtk.ToggleButton()
|
||||
b.set_active(is_active)
|
||||
toggle_connect(b, func)
|
||||
default_button_attrs(b, file_image(img_file), tooltip, show)
|
||||
return b
|
||||
|
||||
|
||||
def rewind_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_REWIND, controls.seek_backward, "Rewind", show)
|
||||
|
||||
def forward_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_FORWARD, controls.seek_forward, "Fast Forward", show)
|
||||
|
||||
def play_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_PLAY, controls.play, "Play", show)
|
||||
|
||||
def pause_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_PAUSE, controls.pause, "Pause", show)
|
||||
|
||||
def stop_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_STOP, controls.stop, "Stop", show)
|
||||
|
||||
def next_button(show):
|
||||
return make_button(gtk.STOCK_MEDIA_NEXT, controls.next, "Next", show)
|
||||
|
||||
def update_button(show):
|
||||
return make_button(gtk.STOCK_REFRESH, sources.library.update_lib, "Update Library", show)
|
||||
|
||||
def open_button(show):
|
||||
def open_func():
|
||||
fsselect.run_chooser2(files.universal_open)
|
||||
return make_button(gtk.STOCK_OPEN, open_func, "Open Anything", show)
|
||||
|
||||
def save_button(show):
|
||||
def save_func():
|
||||
loc = fsselect.select_save()
|
||||
if loc != None:
|
||||
from libsaria.path import export
|
||||
export.save_playlist(loc)
|
||||
return make_button(gtk.STOCK_SAVE, save_func, "Save Current Playlist", show)
|
||||
|
||||
def prefs_button(show):
|
||||
def prefs_func():
|
||||
from ocarina import settings
|
||||
settings.show_page()
|
||||
return make_button(gtk.STOCK_PREFERENCES, prefs_func, "Modify Settings", show)
|
||||
|
||||
def up_button(show):
|
||||
def up_func():
|
||||
from ocarina.body import footer
|
||||
footer.show_more()
|
||||
return make_button(gtk.STOCK_GO_UP, up_func, "Show More Information", show)
|
||||
|
||||
def down_button(show):
|
||||
def down_func():
|
||||
from ocarina.body import footer
|
||||
footer.show_less()
|
||||
return make_button(gtk.STOCK_GO_DOWN, down_func, "Show Less Information", show)
|
||||
|
||||
def goto_button(show):
|
||||
def goto_func():
|
||||
from ocarina import body
|
||||
body.cur_page_goto()
|
||||
return make_button(gtk.STOCK_JUMP_TO, goto_func, "Go To Current Song", show)
|
||||
|
||||
def clear_button(show):
|
||||
def clear_func():
|
||||
from ocarina import body
|
||||
body.cur_page_clear()
|
||||
return make_button(gtk.STOCK_CLEAR, clear_func, "Clear Current Source", show)
|
||||
|
||||
def random_button(is_active, show):
|
||||
return make_toggle("images/random.png", controls.set_rand, "Random", is_active, show)
|
||||
|
||||
def like_button(show):
|
||||
def set_like(like):
|
||||
if like == False:
|
||||
like = None
|
||||
controls.set_like(like)
|
||||
return make_toggle("images/thumbs_up.png", set_like, "I like this", False, show)
|
||||
|
||||
def dislike_button(show):
|
||||
def set_dislike(like):
|
||||
like = not like
|
||||
if like == True:
|
||||
like = None
|
||||
controls.set_like(like)
|
||||
return make_toggle("images/thumbs_down.png", set_dislike, "I don't like this", False, show)
|
||||
|
||||
def volume_button(volume, show):
|
||||
b = gtk.VolumeButton()
|
||||
default_button_attrs(b, None, None, show)
|
||||
b.get_adjustment().set_page_increment(0.05)
|
||||
b.set_value(volume)
|
||||
|
||||
def resize(button):
|
||||
image = b.get_children()[0]
|
||||
icon = image.get_icon_name()[0]
|
||||
image.set_from_icon_name(icon, gtk.ICON_SIZE_MENU)
|
||||
|
||||
def changed(button, value):
|
||||
controls.set_volume(value)
|
||||
resize(button)
|
||||
b.connect("value-changed", changed)
|
||||
resize(b)
|
||||
return b
|
|
@ -1,69 +0,0 @@
|
|||
# Bryan Schumaker (11/25/2010)
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
import tiny
|
||||
import detailed
|
||||
import libsaria
|
||||
from libsaria import audio
|
||||
from ocarina import shortcuts
|
||||
|
||||
footer = gtk.VBox()
|
||||
hsep = gtk.HSeparator()
|
||||
hsep.show()
|
||||
|
||||
footer.pack_start(hsep, True, True)
|
||||
footer.pack_start(tiny.tiny, True, True)
|
||||
footer.pack_start(detailed.detailed, True, True)
|
||||
footer.show()
|
||||
|
||||
def update_pos():
|
||||
time = audio.get_progstr()
|
||||
tiny.update_pos(time)
|
||||
detailed.update_pos(time)
|
||||
return True
|
||||
gobject.timeout_add(500, update_pos)
|
||||
|
||||
def show_more():
|
||||
tiny.hide()
|
||||
detailed.show()
|
||||
libsaria.prefs.set("ocarina.footer.up", True)
|
||||
|
||||
def show_less():
|
||||
tiny.show()
|
||||
detailed.hide()
|
||||
libsaria.prefs.set("ocarina.footer.up", False)
|
||||
|
||||
def toggle_footer():
|
||||
up = libsaria.prefs.get("ocarina.footer.up")
|
||||
if up == True:
|
||||
show_less()
|
||||
else:
|
||||
show_more()
|
||||
shortcuts.register_shortcut("f", toggle_footer)
|
||||
|
||||
up = libsaria.prefs.init("ocarina.footer.up", False)
|
||||
if up == True:
|
||||
show_more()
|
||||
else:
|
||||
show_less()
|
||||
|
||||
def set_art(path):
|
||||
tiny.set_art(path)
|
||||
detailed.set_art(path)
|
||||
|
||||
def on_play():
|
||||
tiny.on_play()
|
||||
detailed.on_play()
|
||||
|
||||
def on_pause():
|
||||
tiny.on_pause()
|
||||
detailed.on_pause()
|
||||
|
||||
def on_load(attrs):
|
||||
tiny.on_load(attrs)
|
||||
detailed.on_load(attrs)
|
||||
|
||||
def on_like(like):
|
||||
detailed.nowplaying.on_like(like)
|
|
@ -1,77 +0,0 @@
|
|||
# Bryan Schumaker (4 / 21 / 2011)
|
||||
|
||||
import gtk
|
||||
from ocarina.body import button
|
||||
import libsaria
|
||||
from libsaria import audio
|
||||
import nowplaying
|
||||
|
||||
detailed = gtk.Notebook()
|
||||
hide = detailed.hide
|
||||
show = detailed.show
|
||||
|
||||
action = gtk.HBox()
|
||||
|
||||
cur_pos = gtk.Label()
|
||||
cur_pos.show()
|
||||
action.pack_start(cur_pos, False, False)
|
||||
|
||||
def slider_update(slider):
|
||||
slider.set_value(audio.get_progress() * 100)
|
||||
|
||||
def slider_scrolled(slider, type, value):
|
||||
audio.seek_prcnt(value / 100.0)
|
||||
|
||||
def slider_clicked(slider, event):
|
||||
prcnt = event.x / float(slider.get_allocation().width)
|
||||
audio.seek_prcnt(prcnt)
|
||||
slider_update(slider)
|
||||
|
||||
def slider_tooltip(slider, event):
|
||||
prcnt = event.x / float(slider.get_allocation().width)
|
||||
slider.set_tooltip_text(audio.get_time_at(prcnt))
|
||||
|
||||
slider = gtk.HScale( gtk.Adjustment(0.0, 0.0, 100.0, 0.1, 1.0, 1.0) )
|
||||
slider.set_size_request(150, 20)
|
||||
slider.set_draw_value(False)
|
||||
slider.set_range(0, 101)
|
||||
slider.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
|
||||
slider.connect("change-value", slider_scrolled)
|
||||
slider.connect("button-press-event", slider_clicked)
|
||||
slider.connect("motion-notify-event", slider_tooltip)
|
||||
slider.show()
|
||||
action.pack_start(slider, True, True)
|
||||
|
||||
def add_button(name, button_func, show = True):
|
||||
b = button_func(show)
|
||||
globals()[name] = b
|
||||
action.pack_start(b, False, False)
|
||||
|
||||
add_button( "PLAY", button.play_button)
|
||||
add_button( "PAUSE", button.pause_button, False)
|
||||
add_button( "STOP", button.stop_button)
|
||||
add_button( "NEXT", button.next_button)
|
||||
add_button( "DOWN", button.down_button)
|
||||
action.show()
|
||||
|
||||
detailed.set_action_widget(action, gtk.PACK_END)
|
||||
detailed.append_page(nowplaying.page, nowplaying.label)
|
||||
|
||||
def set_art(path):
|
||||
nowplaying.set_art(path)
|
||||
|
||||
def update_pos(time):
|
||||
slider_update(slider)
|
||||
cur_pos.set_text(time)
|
||||
|
||||
def on_play():
|
||||
PLAY.hide()
|
||||
PAUSE.show()
|
||||
|
||||
def on_pause():
|
||||
PLAY.show()
|
||||
PAUSE.hide()
|
||||
|
||||
load_attrs = ("title", "artist", "album", "year", "lenstr", "count", "like")
|
||||
def on_load(attrs):
|
||||
nowplaying.on_load(attrs)
|
|
@ -1,78 +0,0 @@
|
|||
# Bryan Schumaker (4 / 21 / 2011)
|
||||
|
||||
import gtk
|
||||
from libsaria import controls
|
||||
from ocarina.body import button
|
||||
from ocarina.body import image
|
||||
|
||||
page = gtk.HBox(False, 5)
|
||||
label = gtk.Label("Now Playing")
|
||||
|
||||
ARTWORK = image.Image()
|
||||
page.pack_start(ARTWORK, False, False)
|
||||
|
||||
def pack_label(box, label):
|
||||
a = gtk.Alignment(0, 0.5, 0, 0)
|
||||
a.add(label)
|
||||
box.pack_start(a)
|
||||
|
||||
TITLE = gtk.Label()
|
||||
ARTIST = gtk.Label("by")
|
||||
ALBUM = gtk.Label("from")
|
||||
tag_box = gtk.VBox(True)
|
||||
view = gtk.Viewport()
|
||||
tags = gtk.ScrolledWindow()
|
||||
view.set_shadow_type(gtk.SHADOW_NONE)
|
||||
tags.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
pack_label(tag_box, TITLE)
|
||||
pack_label(tag_box, ARTIST)
|
||||
pack_label(tag_box, ALBUM)
|
||||
view.add(tag_box)
|
||||
tags.add(view)
|
||||
page.pack_start(tags)
|
||||
|
||||
YEAR = gtk.Label("Year:")
|
||||
LENGTH = gtk.Label("Length:")
|
||||
COUNT = gtk.Label("Play count:")
|
||||
attr_box = gtk.VBox(True)
|
||||
pack_label(attr_box, YEAR)
|
||||
pack_label(attr_box, LENGTH)
|
||||
pack_label(attr_box, COUNT)
|
||||
page.pack_start(attr_box)
|
||||
|
||||
LIKE = button.like_button(True)
|
||||
DISLIKE = button.dislike_button(True)
|
||||
buttons = gtk.HBox(True)
|
||||
buttons.pack_start( LIKE, False, False)
|
||||
buttons.pack_start(DISLIKE, False, False)
|
||||
page.pack_start(buttons, False, False)
|
||||
|
||||
page.show_all()
|
||||
label.show()
|
||||
|
||||
sa_id = None
|
||||
def resize_art(*args):
|
||||
set_art(ARTWORK.get_file())
|
||||
page.disconnect(sa_id)
|
||||
sa_id = page.connect("size-allocate", resize_art)
|
||||
|
||||
def set_art(path):
|
||||
ARTWORK.set_image(path, 64)
|
||||
|
||||
def on_like(like):
|
||||
def _on_like1(like):
|
||||
LIKE.set_active(like == True)
|
||||
DISLIKE.set_active(like == False)
|
||||
def _on_like0(like):
|
||||
button.toggle_call_unconnected(DISLIKE, _on_like1, like)
|
||||
button.toggle_call_unconnected(LIKE, _on_like0, like)
|
||||
|
||||
def on_load(attrs):
|
||||
TITLE.set_text(attrs["title"])
|
||||
ARTIST.set_text("by %s" % attrs["artist"])
|
||||
ALBUM.set_text("from %s" % attrs["album"])
|
||||
YEAR.set_text("Year: %s" % attrs["year"])
|
||||
LENGTH.set_text("Length: %s" % attrs["lenstr"])
|
||||
COUNT.set_text("Play count: %s" % attrs["count"])
|
||||
set_art(attrs["art"])
|
||||
on_like(attrs["like"])
|
|
@ -1,65 +0,0 @@
|
|||
# Bryan Schumaker (2 / 17 / 2011)
|
||||
|
||||
import gtk
|
||||
import pango
|
||||
import ocarina
|
||||
import libsaria
|
||||
from ocarina.body import button
|
||||
from ocarina.body import image
|
||||
|
||||
tiny = gtk.HBox()
|
||||
hide = tiny.hide
|
||||
show = tiny.show
|
||||
|
||||
ARTWORK = image.Image()
|
||||
tiny.pack_start(ARTWORK, False, False)
|
||||
|
||||
now_playing = gtk.Label(ocarina.__vers__)
|
||||
now_playing.set_ellipsize(pango.ELLIPSIZE_END)
|
||||
now_playing.show()
|
||||
|
||||
cur_pos = gtk.Label()
|
||||
duration = gtk.Label()
|
||||
cur_pos.show()
|
||||
duration.show()
|
||||
|
||||
def add_button(name, button_func, show = True):
|
||||
b = button_func(show)
|
||||
globals()[name] = b
|
||||
tiny.pack_start(b, False, False)
|
||||
|
||||
tiny.pack_start(now_playing, True, True)
|
||||
tiny.pack_start( cur_pos, False, False)
|
||||
tiny.pack_start( duration, False, False)
|
||||
add_button( "REWIND", button.rewind_button)
|
||||
add_button("FORWARD", button.forward_button)
|
||||
add_button( "PLAY", button.play_button)
|
||||
add_button( "PAUSE", button.pause_button, False)
|
||||
add_button( "STOP", button.stop_button)
|
||||
add_button( "NEXT", button.next_button)
|
||||
add_button( "UP", button.up_button)
|
||||
|
||||
sa_id = None
|
||||
def resize_art(*args):
|
||||
set_art(ARTWORK.get_file())
|
||||
tiny.disconnect(sa_id)
|
||||
sa_id = tiny.connect("size-allocate", resize_art)
|
||||
|
||||
def set_art(path):
|
||||
ARTWORK.set_image(path, 24)
|
||||
|
||||
def update_pos(pos):
|
||||
cur_pos.set_text(pos)
|
||||
|
||||
def on_play():
|
||||
PLAY.hide()
|
||||
PAUSE.show()
|
||||
|
||||
def on_pause():
|
||||
PLAY.show()
|
||||
PAUSE.hide()
|
||||
|
||||
def on_load(attrs):
|
||||
now_playing.set_text("%s by %s" % (attrs["title"], attrs["artist"]))
|
||||
duration.set_text(" / %s" % attrs["lenstr"])
|
||||
set_art(attrs["art"])
|
|
@ -1,71 +0,0 @@
|
|||
# Bryan Schumaker (11/25/2010)
|
||||
|
||||
import gtk
|
||||
from libsaria import prefs
|
||||
from ocarina.body import button
|
||||
import entry
|
||||
|
||||
header = gtk.VBox()
|
||||
header_body = gtk.HBox()
|
||||
header_sep = gtk.HSeparator()
|
||||
|
||||
header.pack_start(header_body)
|
||||
header.pack_start(header_sep)
|
||||
header.show_all()
|
||||
|
||||
def add_button(name, button):
|
||||
globals()[name] = button
|
||||
header_body.pack_start(button, False, False)
|
||||
|
||||
header_body.pack_start(entry.entry)
|
||||
add_button( "OPEN", button.open_button(True))
|
||||
add_button( "SAVE", button.save_button(True))
|
||||
add_button( "PREFS", button.prefs_button(True))
|
||||
|
||||
sep = gtk.VSeparator()
|
||||
sep.show()
|
||||
header_body.pack_start(sep, False, False)
|
||||
|
||||
add_button("UPDATE", button.update_button(True))
|
||||
add_button( "CLEAR", button.clear_button(True))
|
||||
add_button( "GOTO", button.goto_button(True))
|
||||
add_button("RANDOM", button.random_button(prefs.get("libsaria.random"), True))
|
||||
add_button("VOLUME", button.volume_button(prefs.get("libsaria.audio.volume"), True))
|
||||
|
||||
#import ocarina
|
||||
#from ocarina.components import button
|
||||
#from ocarina.components import entry
|
||||
|
||||
#gtk = ocarina.gtk
|
||||
#header = None
|
||||
#bar = None
|
||||
|
||||
|
||||
#def bar_add(widget, expand = False, fill = False):
|
||||
#bar.pack_start(widget, expand, fill)
|
||||
|
||||
#def init():
|
||||
#global header
|
||||
#global bar
|
||||
|
||||
#header = gtk.VBox()
|
||||
#bar = gtk.HBox()
|
||||
#sep = gtk.HSeparator()
|
||||
#vsep = gtk.VSeparator()
|
||||
#vsep.show()
|
||||
#header.pack_start(bar)
|
||||
#header.pack_start(sep)
|
||||
#header.show_all()
|
||||
|
||||
#bar_add(entry.FilterEntry(), True, True)
|
||||
#bar_add(button.OpenButton())
|
||||
#bar_add(button.SaveButton())
|
||||
#bar_add(button.ExportButton())
|
||||
#bar_add(button.SettingsButton())
|
||||
#bar_add(vsep)
|
||||
#bar_add(button.UpdateButton())
|
||||
#bar_add(button.ClearButton())
|
||||
#bar_add(button.GotoButton())
|
||||
#bar_add(button.RandomButton())
|
||||
#bar_add(button.VolumeButton())
|
||||
#init()
|
|
@ -1,17 +0,0 @@
|
|||
# Bryan Schumaker (4 / 18 / 2011)
|
||||
|
||||
import gtk
|
||||
import ocarina
|
||||
from ocarina import shortcuts
|
||||
from libsaria import sources
|
||||
|
||||
entry = gtk.Entry()
|
||||
entry.show()
|
||||
|
||||
has_focus = entry.is_focus
|
||||
|
||||
def do_filter(entry):
|
||||
sources.filter(entry.get_text())
|
||||
entry.connect("changed", do_filter)
|
||||
|
||||
shortcuts.register_shortcut("slash", entry.grab_focus)
|
|
@ -1,85 +0,0 @@
|
|||
# Bryan Schumaker (04 / 23 / 2011)
|
||||
|
||||
import gtk
|
||||
from ocarina import fsselect
|
||||
from libsaria import sources
|
||||
|
||||
def find_new_width(buf, new_h):
|
||||
w = buf.get_width()
|
||||
h = buf.get_height()
|
||||
if h == 0:
|
||||
h = 1
|
||||
return int( (float(w) / float(h)) * new_h )
|
||||
|
||||
def _resize(img, new_h):
|
||||
buf = img.get_pixbuf()
|
||||
if buf == None:
|
||||
return
|
||||
new_w = find_new_width(buf, new_h)
|
||||
buf = buf.scale_simple(new_w, new_h, gtk.gdk.INTERP_HYPER)
|
||||
if buf == None:
|
||||
return
|
||||
img.clear()
|
||||
img.set_from_pixbuf(buf)
|
||||
|
||||
def resize(img, new_h):
|
||||
if new_h == 0:
|
||||
return
|
||||
new_h = int(new_h)
|
||||
try:
|
||||
_resize(img, new_h)
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
|
||||
class FileImage(gtk.Image):
|
||||
def __init__(self):
|
||||
gtk.Image.__init__(self)
|
||||
self.path = None
|
||||
self.height = 0
|
||||
self.set_has_tooltip(True)
|
||||
self.connect("query-tooltip", self.tooltip)
|
||||
self.show()
|
||||
|
||||
def get_file(self):
|
||||
return self.path
|
||||
|
||||
def set_image(self, path, height):
|
||||
if path != self.path:
|
||||
self.path = path
|
||||
self.height = height
|
||||
self.set_from_file(path)
|
||||
resize(self, height)
|
||||
|
||||
def tooltip(self, image, x, y, keyboard, tip):
|
||||
image = gtk.Image()
|
||||
image.set_from_file(self.path)
|
||||
tip.set_icon(image.get_pixbuf())
|
||||
return True
|
||||
|
||||
|
||||
class Image(gtk.EventBox):
|
||||
def __init__(self):
|
||||
gtk.EventBox.__init__(self)
|
||||
self.image = FileImage()
|
||||
self.add(self.image)
|
||||
self.connect("button-press-event", self.clicked)
|
||||
self.show()
|
||||
|
||||
self.get_file = self.image.get_file
|
||||
self.set_image = self.image.set_image
|
||||
|
||||
def clicked(self, widget, event):
|
||||
if event.button != 1:
|
||||
return
|
||||
id = sources.get_cur_id()
|
||||
if id == -1:
|
||||
return
|
||||
path = fsselect.select_file("Select an image")
|
||||
if path == None:
|
||||
return
|
||||
try:
|
||||
self.set_image(path, self.image.height)
|
||||
sources.set_attr("art", path)
|
||||
except Exception, e:
|
||||
print e
|
|
@ -1,44 +0,0 @@
|
|||
# Bryan Schumaker (4 / 17 / 2011)
|
||||
|
||||
import gtk
|
||||
import header
|
||||
import footer
|
||||
SHRINK = gtk.SHRINK
|
||||
GROW = gtk.FILL | gtk.EXPAND
|
||||
|
||||
class OcarinaPage(gtk.Table):
|
||||
def __init__(self, content, label):
|
||||
gtk.Table.__init__(self, 3, 1, False)
|
||||
self.content = content
|
||||
self.label = label
|
||||
self.block_shortcuts = False
|
||||
self.attach_center(content)
|
||||
self.show()
|
||||
|
||||
def visible(self):
|
||||
self.attach_top(header.header)
|
||||
self.attach_bottom(footer.footer)
|
||||
|
||||
def invisible(self):
|
||||
if header.header.get_parent() == self:
|
||||
self.remove(header.header)
|
||||
if footer.footer.get_parent() == self:
|
||||
self.remove(footer.footer)
|
||||
|
||||
def attach_top(self, content):
|
||||
self.attach(content, 0, 1, 0, 1, GROW, SHRINK)
|
||||
|
||||
def attach_center(self, content):
|
||||
self.attach(content, 0, 1, 1, 2)
|
||||
|
||||
def attach_bottom(self, content):
|
||||
self.attach(content, 0, 1, 2, 3, GROW, SHRINK)
|
||||
|
||||
def filter(self, text):
|
||||
pass
|
||||
|
||||
def goto(self):
|
||||
pass
|
||||
|
||||
def clear(self):
|
||||
pass
|
|
@ -1,69 +0,0 @@
|
|||
# Bryan Schumaker (4 / 20 / 2011)
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
|
||||
import libsaria
|
||||
import queue
|
||||
from ocarina import body
|
||||
from ocarina import settings
|
||||
from ocarina.body import footer
|
||||
from libsaria import callbacks
|
||||
import playlist
|
||||
import library
|
||||
|
||||
def on_play():
|
||||
footer.on_play()
|
||||
callbacks.on_play = on_play
|
||||
|
||||
def on_pause():
|
||||
footer.on_pause()
|
||||
callbacks.on_pause = on_pause
|
||||
|
||||
def on_load(file, attrs):
|
||||
footer.on_load(attrs)
|
||||
queue.refresh()
|
||||
body.cur_page_goto()
|
||||
callbacks.on_load = on_load
|
||||
|
||||
def on_like(like):
|
||||
footer.on_like(like)
|
||||
callbacks.on_like = on_like
|
||||
|
||||
|
||||
# A bit of a hack to force setting album art in the main thread
|
||||
# Basically, I create a new signal and trigger it when new album
|
||||
# art arrives
|
||||
gobject.signal_new("get_art", gobject.GObject, gobject.SIGNAL_RUN_LAST,
|
||||
gobject.TYPE_NONE,
|
||||
(gobject.TYPE_INT, gobject.TYPE_STRING))
|
||||
|
||||
def on_get_art_helper(obj, id, path):
|
||||
if id == libsaria.sources.get_cur_id():
|
||||
footer.set_art(path)
|
||||
|
||||
on_get_art_obj = gobject.GObject()
|
||||
on_get_art_obj.connect("get_art", on_get_art_helper)
|
||||
|
||||
def on_get_art(path, id):
|
||||
on_get_art_obj.emit("get_art", id, path)
|
||||
callbacks.on_get_art = on_get_art
|
||||
|
||||
def on_load_playlist():
|
||||
playlist.refresh()
|
||||
callbacks.on_load_playlist = on_load_playlist
|
||||
|
||||
def library_updated():
|
||||
library.refresh()
|
||||
settings.library.refresh()
|
||||
callbacks.on_library_updated = library_updated
|
||||
|
||||
def on_queue_changed():
|
||||
queue.refresh()
|
||||
callbacks.on_queue_changed = on_queue_changed
|
||||
|
||||
def on_refilter():
|
||||
queue.refilter()
|
||||
playlist.refilter()
|
||||
library.refilter()
|
||||
callbacks.on_refilter = on_refilter
|
|
@ -1,86 +0,0 @@
|
|||
# Bryan Schumaker (June 2010)
|
||||
|
||||
import ocarina
|
||||
import gobject
|
||||
import os
|
||||
|
||||
gtk = ocarina.gtk
|
||||
libsaria = ocarina.libsaria
|
||||
|
||||
#FS_OK = gobject.signal_new("filesystem_ok", gtk.FileChooserDialog,
|
||||
# gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
|
||||
# (gtk.Dialog, int))
|
||||
#print FS_OK
|
||||
|
||||
#print gobject.signal_query(FS_OK)
|
||||
#print gobject.signal_query(gtk.RESPONSE_OK)
|
||||
chooser_window = None
|
||||
chooser_widget = None
|
||||
|
||||
def make_chooser(title, action):
|
||||
buttons = (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OK, gtk.RESPONSE_OK)
|
||||
chooser = gtk.FileChooserDialog(title, action=action, buttons=buttons)
|
||||
return chooser
|
||||
|
||||
def make_chooser2(title, callback):
|
||||
global chooser_window
|
||||
global chooser_widget
|
||||
chooser_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
|
||||
chooser_box = gtk.VBox(spacing = 0)
|
||||
button_box = gtk.HBox()
|
||||
chooser_widget = gtk.FileChooserWidget()
|
||||
open_button = gtk.Button(stock=gtk.STOCK_OK)
|
||||
close_button = gtk.Button(stock=gtk.STOCK_CANCEL)
|
||||
button_box.pack_end(open_button, False, False, 10)
|
||||
button_box.pack_end(close_button, False, False)
|
||||
chooser_box.pack_start(chooser_widget, True, True, 10)
|
||||
chooser_box.pack_start(button_box, False, False, 10)
|
||||
|
||||
size = close_button.size_request()
|
||||
open_button.set_size_request(size[0], size[1])
|
||||
chooser_widget.connect("file-activated", select_path, callback)
|
||||
open_button.connect("clicked", select_path, callback)
|
||||
close_button.connect("clicked", hide_chooser)
|
||||
|
||||
chooser_window.add(chooser_box)
|
||||
chooser_window.resize(800, 600)
|
||||
chooser_window.show_all()
|
||||
|
||||
def hide_chooser(button):
|
||||
global chooser_window
|
||||
chooser_window.hide()
|
||||
|
||||
def select_path(widget, callback):
|
||||
global chooser_widget
|
||||
global chooser_window
|
||||
chooser_window.hide()
|
||||
uri = chooser_widget.get_uri()
|
||||
if uri[:7] == "file://":
|
||||
uri = uri[7:]
|
||||
uri = uri.replace("%20", " ")
|
||||
callback(uri)
|
||||
|
||||
def run_chooser2(callback):
|
||||
make_chooser2("title", callback)
|
||||
|
||||
def run_chooser(chooser):
|
||||
file = None
|
||||
if chooser.run() == gtk.RESPONSE_OK:
|
||||
file = chooser.get_filename()
|
||||
chooser.hide()
|
||||
return file
|
||||
|
||||
# Use for selecting a file through the GUI
|
||||
def select_file(title = "Select a song"):
|
||||
chooser = make_chooser(title, gtk.FILE_CHOOSER_ACTION_OPEN)
|
||||
return run_chooser(chooser)
|
||||
|
||||
# Use for selecting a directory through the GUI
|
||||
def select_dir(title = "Select a directory"):
|
||||
chooser = make_chooser(title, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
|
||||
return run_chooser(chooser)
|
||||
|
||||
def select_save(title = "Select a location"):
|
||||
chooser = make_chooser(title, gtk.FILE_CHOOSER_ACTION_SAVE)
|
||||
return run_chooser(chooser)
|
|
@ -1,47 +0,0 @@
|
|||
# Bryan Schumaker (5 / 20 / 2011)
|
||||
|
||||
import libsaria
|
||||
import sources
|
||||
import body
|
||||
|
||||
library = libsaria.sources.library
|
||||
lib_page = sources.Source()
|
||||
LIB_PAGE = body.add_page(lib_page, "Library")
|
||||
LIB_PAGE.goto = lib_page.goto
|
||||
|
||||
def set_label_text():
|
||||
LIB_PAGE.label.set_text("Library (%s)" % library.num_visible())
|
||||
|
||||
def fill_library():
|
||||
songs = libsaria.sources.list_library(*sources.column.attrs)
|
||||
lib_page.insert(songs)
|
||||
set_label_text()
|
||||
fill_library()
|
||||
|
||||
def refresh():
|
||||
lib_page.clear()
|
||||
fill_library()
|
||||
|
||||
def refilter():
|
||||
lib_page.refilter()
|
||||
set_label_text()
|
||||
|
||||
import playlist
|
||||
import queue
|
||||
|
||||
def clear():
|
||||
queue.clear()
|
||||
playlist.clear()
|
||||
library.reset()
|
||||
lib_page.clear()
|
||||
refresh()
|
||||
LIB_PAGE.clear = clear
|
||||
|
||||
menu_items = [
|
||||
("Add to Queue", queue.add_to_queue),
|
||||
("Add to Playlist", playlist.add_to_playlist),
|
||||
]
|
||||
def show_menu(event):
|
||||
m = sources.Menu(lib_page, menu_items)
|
||||
m.show(event)
|
||||
lib_page.set_right_click(show_menu)
|
|
@ -1,54 +0,0 @@
|
|||
# Bryan Schumaker (11/26/2010)
|
||||
|
||||
import libsaria
|
||||
import sources
|
||||
import body
|
||||
|
||||
playlist = libsaria.sources.playlist
|
||||
playlist_page = sources.Source()
|
||||
PLAYLIST_PAGE = body.add_page(playlist_page, "Playlist")
|
||||
PLAYLIST_PAGE.goto = playlist_page.goto
|
||||
|
||||
def set_label_text():
|
||||
PLAYLIST_PAGE.label.set_text("Playlist (%s)" % playlist.num_visible())
|
||||
|
||||
def fill_playlist():
|
||||
songs = libsaria.sources.list_playlist(*sources.column.attrs)
|
||||
playlist_page.insert(songs)
|
||||
set_label_text()
|
||||
fill_playlist()
|
||||
|
||||
def refresh():
|
||||
playlist_page.clear()
|
||||
fill_playlist()
|
||||
|
||||
def refilter():
|
||||
playlist_page.refilter()
|
||||
playlist_page.goto()
|
||||
set_label_text()
|
||||
|
||||
def clear():
|
||||
playlist_page.clear()
|
||||
playlist.reset()
|
||||
refresh()
|
||||
PLAYLIST_PAGE.clear = clear
|
||||
|
||||
def add_to_playlist(menu):
|
||||
ids = menu.source.get_selected_ids()
|
||||
playlist.add_ids(ids)
|
||||
refresh()
|
||||
|
||||
def rm_from_playlist(menu):
|
||||
ids = menu.source.get_selected_ids()
|
||||
playlist.rm_ids(ids)
|
||||
refresh()
|
||||
|
||||
import queue
|
||||
menu_items = [
|
||||
("Add to Queue", queue.add_to_queue),
|
||||
("Remove from Playlist", rm_from_playlist),
|
||||
]
|
||||
def show_menu(event):
|
||||
m = sources.Menu(playlist_page, menu_items)
|
||||
m.show(event)
|
||||
playlist_page.set_right_click(show_menu)
|
|
@ -1,58 +0,0 @@
|
|||
# Bryan Schumaker (12/12/2010)
|
||||
|
||||
import libsaria
|
||||
import sources
|
||||
import body
|
||||
|
||||
queue = libsaria.sources.queue
|
||||
queue_page = sources.Source()
|
||||
QUEUE_PAGE = body.add_page(queue_page, "Queue")
|
||||
QUEUE_PAGE.goto = queue_page.goto
|
||||
|
||||
def set_label_text():
|
||||
QUEUE_PAGE.label.set_text("Queue (%s)" % queue.num_visible())
|
||||
|
||||
def set_visible():
|
||||
if queue.num_visible() == 0:
|
||||
body.hide_page(QUEUE_PAGE)
|
||||
else:
|
||||
body.show_page(QUEUE_PAGE)
|
||||
|
||||
def fill_queue():
|
||||
songs = libsaria.sources.list_queue(*sources.column.attrs)
|
||||
queue_page.insert(songs)
|
||||
set_label_text()
|
||||
set_visible()
|
||||
fill_queue()
|
||||
|
||||
def refresh():
|
||||
queue_page.clear()
|
||||
fill_queue()
|
||||
|
||||
def refilter():
|
||||
queue_page.refilter()
|
||||
set_label_text()
|
||||
|
||||
def clear():
|
||||
queue_page.clear()
|
||||
queue.reset()
|
||||
refresh()
|
||||
QUEUE_PAGE.clear = clear
|
||||
|
||||
def add_to_queue(menu):
|
||||
ids = menu.source.get_selected_ids()
|
||||
queue.add_ids(ids)
|
||||
refresh()
|
||||
|
||||
def rm_from_queue(menu):
|
||||
ids = menu.source.get_selected_ids()
|
||||
queue.rm_ids(ids)
|
||||
refresh()
|
||||
|
||||
menu_items = [
|
||||
("Remove from Queue", rm_from_queue),
|
||||
]
|
||||
def show_menu(event):
|
||||
m = sources.Menu(queue_page, menu_items)
|
||||
m.show(event)
|
||||
queue_page.set_right_click(show_menu)
|
|
@ -1,44 +0,0 @@
|
|||
# Bryan Schumaker (6 / 18 / 2011)
|
||||
|
||||
import gtk
|
||||
|
||||
from ocarina import sources
|
||||
from ocarina import body
|
||||
|
||||
settings_page = gtk.VBox()
|
||||
settings_page.show()
|
||||
SETTINGS_PAGE = body.add_page(settings_page, "Settings")
|
||||
|
||||
categories = gtk.Notebook()
|
||||
settings_page.pack_start(categories, True, True)
|
||||
settings_page.show_all()
|
||||
|
||||
close_button = gtk.Button("Close", gtk.STOCK_CLOSE)
|
||||
close_button.set_relief(gtk.RELIEF_NONE)
|
||||
categories.set_action_widget(close_button, gtk.PACK_END)
|
||||
close_button.show()
|
||||
|
||||
def hide_settings(*args):
|
||||
body.hide_page(SETTINGS_PAGE)
|
||||
body.switch_to_page_n(0)
|
||||
close_button.connect("clicked", hide_settings)
|
||||
hide_settings()
|
||||
|
||||
def show_settings():
|
||||
body.show_page(SETTINGS_PAGE)
|
||||
|
||||
def show_page():
|
||||
show_settings()
|
||||
body.switch_to_page(SETTINGS_PAGE)
|
||||
|
||||
def add_category(module):
|
||||
label = gtk.Label(module.text)
|
||||
label.show()
|
||||
categories.append_page(module.page, label)
|
||||
module.page.show()
|
||||
|
||||
import library
|
||||
add_category(library)
|
||||
|
||||
import experimental
|
||||
add_category(experimental)
|
|
@ -1,21 +0,0 @@
|
|||
# Bryan Schumaker (6 / 18 / 2011)
|
||||
|
||||
import gtk
|
||||
import libsaria
|
||||
|
||||
page = gtk.VBox()
|
||||
text = "Experimental"
|
||||
|
||||
def toggled(button, func):
|
||||
func(button.get_active())
|
||||
|
||||
def make_check_button(text, func, active):
|
||||
button = gtk.CheckButton(text)
|
||||
button.set_active(active)
|
||||
button.connect("toggled", toggled, func)
|
||||
return button
|
||||
|
||||
SERVER = make_check_button("Enable web server", libsaria.server.toggle_state, libsaria.server.get_state())
|
||||
|
||||
page.pack_start(SERVER, False, False)
|
||||
page.show_all()
|
|
@ -1,47 +0,0 @@
|
|||
# Bryan Schumaker (6 / 18 / 2011)
|
||||
|
||||
import gtk
|
||||
import libsaria
|
||||
|
||||
page = gtk.VBox()
|
||||
text = "Library"
|
||||
panels = {}
|
||||
|
||||
def remove_path(button, path):
|
||||
page.remove(panels[path])
|
||||
del panels[path]
|
||||
libsaria.sources.library.rm_path(path)
|
||||
|
||||
def add_panel(panel, path):
|
||||
full_box = gtk.VBox()
|
||||
full_box.pack_start(panel)
|
||||
full_box.pack_start(gtk.HSeparator())
|
||||
full_box.show_all()
|
||||
panels[path] = full_box
|
||||
page.pack_start(full_box, False, False)
|
||||
|
||||
def show_source(path, lib):
|
||||
panel = gtk.HBox()
|
||||
info_box = gtk.VBox()
|
||||
|
||||
path_lbl = gtk.Label()
|
||||
path_lbl.set_markup("<span size='xx-large' weight='bold'>%s</span>" % path)
|
||||
count_lbl = gtk.Label()
|
||||
count_lbl.set_markup("<span size='large'>%s files</span>" % len(lib))
|
||||
remove_button = gtk.Button("Remove", gtk.STOCK_REMOVE)
|
||||
remove_button.connect("clicked", remove_path, path)
|
||||
|
||||
info_box.pack_start(path_lbl)
|
||||
info_box.pack_start(count_lbl)
|
||||
panel.pack_start(info_box)
|
||||
panel.pack_start(remove_button, False, False)
|
||||
add_panel(panel, path)
|
||||
|
||||
def refresh():
|
||||
for path in panels:
|
||||
page.remove(panels[path])
|
||||
|
||||
for path, lib in libsaria.sources.library.list_paths():
|
||||
show_source(path, lib)
|
||||
refresh()
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
# Bryan Schumaker (3 / 11 / 2011)
|
||||
|
||||
import gtk
|
||||
from libsaria import controls
|
||||
|
||||
keyval_name = gtk.gdk.keyval_name
|
||||
shortcut_map = {}
|
||||
|
||||
def null_shortcut():
|
||||
return False
|
||||
|
||||
# Setting allow_filter_focus to True means that the
|
||||
# registered shortcut will always run, even if the
|
||||
# filter entry currently has focus
|
||||
def register_shortcut(key, func, allow_filter_focus = False):
|
||||
shortcut_map[key] = (func, allow_filter_focus)
|
||||
|
||||
def key_pressed(widget, event):
|
||||
from ocarina import body
|
||||
from ocarina.body.header import entry
|
||||
|
||||
name = keyval_name(event.keyval)
|
||||
func, allow_filter_focus = shortcut_map.get(name, (null_shortcut, False))
|
||||
if (entry.has_focus() and not allow_filter_focus):
|
||||
return
|
||||
if func() == False:
|
||||
return False
|
||||
widget.emit_stop_by_name("key-press-event")
|
||||
return True
|
||||
|
||||
register_shortcut("space", controls.toggle_play)
|
||||
register_shortcut( "Left", controls.seek_backward)
|
||||
register_shortcut("Right", controls.seek_forward)
|
||||
register_shortcut( "n", controls.next)
|
||||
register_shortcut( "s", controls.stop)
|
|
@ -1,26 +0,0 @@
|
|||
# Bryan Schumaker (2 / 11 / 2011)
|
||||
|
||||
import gtk
|
||||
|
||||
import listview
|
||||
import menu
|
||||
|
||||
Menu = menu.Menu
|
||||
|
||||
class Source(gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
gtk.ScrolledWindow.__init__(self)
|
||||
self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
self.listview = listview.ListView()
|
||||
self.add(self.listview)
|
||||
self.show()
|
||||
|
||||
# Function pointer declarations
|
||||
self.get_selected_ids = self.listview.get_selected_ids
|
||||
self.set_right_click = self.listview.set_right_click
|
||||
self.set_filter_func = self.listview.set_filter_func
|
||||
self.refilter = self.listview.refilter
|
||||
self.insert = self.listview.insert_rows
|
||||
self.clear = self.listview.clear
|
||||
self.goto = self.listview.goto
|
|
@ -1,20 +0,0 @@
|
|||
# Bryan Schumaker (2 / 12 / 2011)
|
||||
|
||||
import gtk
|
||||
|
||||
attrs = ("id", "track", "title", "lenstr", "artist", "album", "year")
|
||||
columns = ["Id", "#", "Title", "Length", "Artist", "Album", "Year"]
|
||||
col_width = [ 2, 20, 300, 60, 125, 125, 50]
|
||||
|
||||
cell = gtk.CellRendererText()
|
||||
cell.set_fixed_height_from_font(1)
|
||||
|
||||
class Column(gtk.TreeViewColumn):
|
||||
def __init__(self, index, label):
|
||||
gtk.TreeViewColumn.__init__(self, label, cell)
|
||||
self.add_attribute(cell, 'text', index)
|
||||
self.set_resizable(True)
|
||||
self.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
|
||||
self.set_min_width(2)
|
||||
self.set_max_width(700)
|
||||
self.set_fixed_width(col_width[index])
|
|
@ -1,7 +0,0 @@
|
|||
# Bryan Schumaker (2 / 12 / 2011)
|
||||
|
||||
import gtk
|
||||
|
||||
class List(gtk.ListStore):
|
||||
def __init__(self):
|
||||
gtk.ListStore.__init__(self, int, str, str, str, str, str, int)
|
|
@ -1,142 +0,0 @@
|
|||
# Bryan Schumaker (2 / 12 / 2011)
|
||||
|
||||
import gtk
|
||||
import list
|
||||
import column
|
||||
import libsaria
|
||||
|
||||
BUTTON_RIGHT = 3
|
||||
is_visible = libsaria.sources.is_visible
|
||||
|
||||
class ListView(gtk.TreeView):
|
||||
def __init__(self):
|
||||
gtk.TreeView.__init__(self)
|
||||
self.list = list.List()
|
||||
|
||||
for index, label in enumerate(column.columns):
|
||||
col = column.Column(index, label)
|
||||
if index != 0:
|
||||
self.append_column(col)
|
||||
|
||||
self.set_rules_hint(True)
|
||||
#self.set_has_tooltip(True)
|
||||
self.set_fixed_height_mode(True)
|
||||
|
||||
self.filter_model = self.list.filter_new()
|
||||
self.set_model(self.filter_model)
|
||||
|
||||
self.selection = self.get_selection()
|
||||
self.selection.set_mode(gtk.SELECTION_MULTIPLE)
|
||||
|
||||
self.connect("row-activated", self.double_click)
|
||||
self.connect("button-release-event", self.button_click)
|
||||
#self.connect("query-tooltip", self.query_tooltip)
|
||||
|
||||
self.set_filter_func(self.song_is_visible)
|
||||
self.insert = self.list.insert
|
||||
self.show()
|
||||
|
||||
def freeze(self):
|
||||
self.freeze_child_notify()
|
||||
self.set_model(None)
|
||||
self.hide()
|
||||
|
||||
def thaw(self):
|
||||
self.show()
|
||||
self.set_model(self.filter_model)
|
||||
self.thaw_child_notify()
|
||||
|
||||
def clear(self):
|
||||
self.freeze()
|
||||
self.list.clear()
|
||||
self.thaw()
|
||||
|
||||
def insert_rows(self, rows):
|
||||
self.freeze()
|
||||
ins_next = 0
|
||||
insert = self.insert
|
||||
for row in rows:
|
||||
insert(ins_next, row)
|
||||
ins_next += 1
|
||||
self.thaw()
|
||||
|
||||
def right_click(self, event):
|
||||
pass
|
||||
|
||||
def set_right_click(self, func):
|
||||
self.right_click = func
|
||||
|
||||
def double_click(self, widget, path, column):
|
||||
model = self.get_model()
|
||||
iter = model.get_iter(path)
|
||||
row = model[iter]
|
||||
libsaria.sources.play_id(row[0])
|
||||
|
||||
def button_click(self, widget, event):
|
||||
if event.button == BUTTON_RIGHT:
|
||||
self.right_click(event)
|
||||
|
||||
def get_selected_ids(self):
|
||||
res = []
|
||||
def insert_func(tree, path, iter, func):
|
||||
func(tree[iter][0])
|
||||
self.selection.selected_foreach(insert_func, res.append)
|
||||
return res
|
||||
|
||||
def song_is_visible(self, list, iter):
|
||||
return is_visible(list[iter][0])
|
||||
|
||||
def set_filter_func(self, func):
|
||||
self.filter_model.set_visible_func(func)
|
||||
|
||||
def refilter(self):
|
||||
self.freeze()
|
||||
self.filter_model.refilter()
|
||||
self.thaw()
|
||||
|
||||
def goto(self, *args):
|
||||
id = libsaria.sources.get_cur_id()
|
||||
if id == -1: # Bad id
|
||||
return
|
||||
vis = self.get_visible_rect()
|
||||
if vis[3] == 0: # The widget hasn't been realized yet
|
||||
return
|
||||
for index, row in enumerate(self.filter_model):
|
||||
if row[0] == id:
|
||||
col = self.get_column(0)
|
||||
row_vis = self.get_cell_area(index, col)
|
||||
if row_vis[3] > 0:
|
||||
n = vis[3] / row_vis[3]
|
||||
path = index - (n / 2)
|
||||
if path < 0:
|
||||
path = 0
|
||||
self.scroll_to_cell(path, None, True, 0, 0)
|
||||
self.set_cursor_on_cell(index, None, None, False)
|
||||
return
|
||||
|
||||
#def query_tooltip(self, widget, x, y, keyboard, tip):
|
||||
#row = self.get_dest_row_at_pos(x,y)
|
||||
#if row == None:
|
||||
#return False
|
||||
#iter = self.filter_model.get_iter(row[0])
|
||||
#id = self.filter_model[iter][0]
|
||||
|
||||
##attrs = get_attrs(id, "art", "title", "artist", "album", "year", "lenstr", "count")
|
||||
#attrs = get_attrs(id, "title", "artist", "album", "year", "lenstr", "count")
|
||||
|
||||
##art = image.Image()
|
||||
##art.set_from_file(attrs[0])
|
||||
##art.set_height(52)
|
||||
##tip.set_icon(art.get_pixbuf())
|
||||
|
||||
#tip.set_markup("<b>%s</b>\nby %s\nfrom %s" %
|
||||
#(attrs[0].replace("&", "&"),
|
||||
#attrs[1].replace("&", "&"),
|
||||
#attrs[2].replace("&", "&"))
|
||||
#)
|
||||
|
||||
#extra = gtk.Label()
|
||||
#extra.set_markup(" Year: %s\n Length: %s\n Play count: %s" %
|
||||
#(attrs[3], attrs[4], attrs[5]) )
|
||||
#tip.set_custom(extra)
|
||||
#return True
|
|
@ -1,28 +0,0 @@
|
|||
# Bryan Schumaker (2 / 26 / 2011)
|
||||
|
||||
import gtk
|
||||
import libsaria
|
||||
|
||||
common = [
|
||||
("Pause after current song", libsaria.controls.do_pause_after)
|
||||
]
|
||||
|
||||
class MenuItem(gtk.MenuItem):
|
||||
def __init__(self, source, text, func):
|
||||
gtk.MenuItem.__init__(self, text)
|
||||
self.source = source
|
||||
if func:
|
||||
self.connect("activate", func)
|
||||
self.show()
|
||||
|
||||
class Menu(gtk.Menu):
|
||||
def __init__(self, source, items):
|
||||
gtk.Menu.__init__(self)
|
||||
for (text, func) in common:
|
||||
self.append(MenuItem(source, text, func))
|
||||
self.append(MenuItem(source, None, None))
|
||||
for (text, func) in items:
|
||||
self.append(MenuItem(source, text, func))
|
||||
|
||||
def show(self, event):
|
||||
self.popup(None, None, None, event.button, event.time)
|
|
@ -1,52 +0,0 @@
|
|||
# Bryan Schumaker (8/13/2010)
|
||||
|
||||
import gtk
|
||||
import ocarina
|
||||
import libsaria
|
||||
import body
|
||||
import shortcuts
|
||||
from libsaria.path import files
|
||||
|
||||
TARGET_TYPE_URI_LIST = 80
|
||||
DND_MASK = gtk.DEST_DEFAULT_MOTION | gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP
|
||||
DND_LIST = [("text/uri-list", 0, TARGET_TYPE_URI_LIST)]
|
||||
|
||||
width = libsaria.prefs.init("ocarina.window.width", 800)
|
||||
height = libsaria.prefs.init("ocarina.window.height", 600)
|
||||
|
||||
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
window.resize(width, height)
|
||||
window.connect("delete-event", ocarina.quit)
|
||||
window.connect("key-press-event", shortcuts.key_pressed)
|
||||
window.add(body.body)
|
||||
window.show()
|
||||
|
||||
def grab_focus():
|
||||
window.set_focus(None)
|
||||
shortcuts.register_shortcut("Escape", grab_focus, True)
|
||||
|
||||
def set_title(new_title = None):
|
||||
if new_title == None:
|
||||
new_title = ocarina.__vers__
|
||||
window.set_title(new_title)
|
||||
set_title()
|
||||
|
||||
def set_icon(icon = "images/ocarina.png"):
|
||||
window.set_icon_from_file(icon)
|
||||
set_icon()
|
||||
|
||||
def resized(widget, geom):
|
||||
if libsaria.prefs.get("ocarina.window.width") != geom.width:
|
||||
libsaria.prefs.set("ocarina.window.width", geom.width)
|
||||
if libsaria.prefs.get("ocarina.window.height") != geom.height:
|
||||
libsaria.prefs.set("ocarina.window.height", geom.height)
|
||||
window.connect("size-allocate", resized)
|
||||
|
||||
def dnd_receive(widget, context, x, y, selection, type, time):
|
||||
if type == TARGET_TYPE_URI_LIST:
|
||||
uri = selection.data.strip('\r\n\x00')
|
||||
for file in uri.split():
|
||||
file = file[7:]
|
||||
files.universal_open(file)
|
||||
window.connect("drag-data-received", dnd_receive)
|
||||
window.drag_dest_set(DND_MASK, DND_LIST, gtk.gdk.ACTION_COPY)
|
|
@ -1,103 +0,0 @@
|
|||
# Bryan Schumaker (11/27/2010)
|
||||
|
||||
import ocarina
|
||||
from ocarina import footer
|
||||
from ocarina.components import image
|
||||
from ocarina.components import label
|
||||
import re
|
||||
|
||||
libsaria = ocarina.libsaria
|
||||
from libsaria import web
|
||||
from libsaria import xm
|
||||
from libsaria import cache
|
||||
|
||||
__NAME__ = "Lyrics"
|
||||
gtk = ocarina.gtk
|
||||
|
||||
lyrics = gtk.ScrolledWindow()
|
||||
page = gtk.HBox(False, 5)
|
||||
text = gtk.TextView()
|
||||
buffer = text.get_buffer()
|
||||
|
||||
lyrics.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
|
||||
page.pack_start(image.AlbumArt(), False, False)
|
||||
|
||||
text.set_editable(False)
|
||||
lyrics.add(text)
|
||||
page.pack_start(lyrics)
|
||||
|
||||
page.show_all()
|
||||
|
||||
url = "http://lyrics.wikia.com/api.php?"
|
||||
|
||||
def decode_line(line):
|
||||
string = ""
|
||||
for c in line.split(";"):
|
||||
if len(c) == 0:
|
||||
continue
|
||||
try:
|
||||
val = int(c[2:])
|
||||
string += chr(val)
|
||||
except:
|
||||
pass
|
||||
return string
|
||||
|
||||
def decode(file, code):
|
||||
lines = []
|
||||
for line in code:
|
||||
lines.append(decode_line(line))
|
||||
string = "\n".join(lines)
|
||||
file.write(string)
|
||||
|
||||
def parse_full(file, lyrics):
|
||||
req = web.Url(lyrics)
|
||||
res = None
|
||||
for line in req.open():
|
||||
if re.match("<div class=\'lyricbox\'>(.*?)", line):
|
||||
res = line
|
||||
split = res.split("</div>")
|
||||
code = split[len(split) - 1]
|
||||
decode(file, code.split("<br />"))
|
||||
|
||||
def parse(file, res):
|
||||
doc = xm.parse(res)
|
||||
result = xm.child(doc)
|
||||
url_node = xm.get_elements(result, "url")[0]
|
||||
lyrics = xm.child(url_node).data
|
||||
parse_full(file, lyrics)
|
||||
|
||||
def fetch_lyrics(file, artist, title):
|
||||
req = web.Url(url)
|
||||
req["artist"] = artist
|
||||
req["song"] = title
|
||||
req["fmt"] = "xml"
|
||||
try:
|
||||
parse(file, req.open())
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def set_lyrics(filepath):
|
||||
artist, title = libsaria.sources.get_attrs("artist", "title")
|
||||
cached = cache[artist]
|
||||
file = cached.get("%s.txt" % title, fetch_lyrics, artist, title)
|
||||
if file != None:
|
||||
fin = open(file)
|
||||
buffer.set_text(fin.read())
|
||||
else:
|
||||
buffer.set_text("")
|
||||
|
||||
def start():
|
||||
footer.add_page("Lyrics", page)
|
||||
libsaria.event.invite("POSTLOAD", set_lyrics, True)
|
||||
|
||||
def stop():
|
||||
footer.remove_page("Lyrics")
|
||||
|
||||
def check_version():
|
||||
if libsaria.__major__ != 4:
|
||||
return False
|
||||
if libsaria.__minor__ == 4:
|
||||
return True
|
||||
return False
|
|
@ -1,36 +0,0 @@
|
|||
# Bryan Schumaker (12/12/2010)
|
||||
|
||||
import pynotify
|
||||
import ocarina
|
||||
libsaria = ocarina.libsaria
|
||||
get_attrs = libsaria.sources.get_attrs
|
||||
image = ocarina.components.image.Image()
|
||||
|
||||
__NAME__ = "Notify"
|
||||
|
||||
def notify(*args):
|
||||
title, artist, art = get_attrs("title", "artist", "art")
|
||||
|
||||
try:
|
||||
image.set_from_file(art)
|
||||
image.set_height(64)
|
||||
n = pynotify.Notification(title, "by %s" % artist)
|
||||
n.set_icon_from_pixbuf(image.get_pixbuf())
|
||||
n.set_timeout(10)
|
||||
n.show()
|
||||
except Exception, e:
|
||||
pass
|
||||
|
||||
def start():
|
||||
if pynotify.init(ocarina.__vers__):
|
||||
libsaria.event.invite("POSTLOAD", notify)
|
||||
|
||||
def stop():
|
||||
pass
|
||||
|
||||
def check_version():
|
||||
if libsaria.__major__ != 4:
|
||||
return False
|
||||
if libsaria.__minor__ == 4:
|
||||
return True
|
||||
return True
|
|
@ -1,56 +0,0 @@
|
|||
# Bryan Schumaker (8/14/2010)
|
||||
|
||||
import ocarina
|
||||
import webkit
|
||||
from ocarina import body
|
||||
|
||||
__NAME__ = "Web Radio"
|
||||
|
||||
libsaria = ocarina.libsaria
|
||||
path = libsaria.path
|
||||
audio = libsaria.audio
|
||||
gtk = ocarina.gtk
|
||||
|
||||
box = gtk.VBox()
|
||||
sel = gtk.combo_box_new_text()
|
||||
page = gtk.ScrolledWindow()
|
||||
web = webkit.WebView()
|
||||
|
||||
sel.append_text("Select a station:")
|
||||
sel.append_text("Groove Shark")
|
||||
sel.append_text("Pandora")
|
||||
sel.set_active(0)
|
||||
|
||||
page.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
page.add(web)
|
||||
|
||||
html = path.join(path.cwd(), "html")
|
||||
radio = path.join(html, "web_radio.html")
|
||||
web.open(radio)
|
||||
|
||||
box.pack_start(sel, False, False)
|
||||
box.pack_start(page)
|
||||
box.show_all()
|
||||
|
||||
urls = [radio, "http://www.grooveshark.com", "http://www.pandora.com"]
|
||||
|
||||
def combo_box_changed(box):
|
||||
model = box.get_model()
|
||||
index = box.get_active()
|
||||
if index != None:
|
||||
web.open(urls[index])
|
||||
|
||||
sel.connect("changed", combo_box_changed)
|
||||
|
||||
def start():
|
||||
body.add_page("Web Radio", box, False, False)
|
||||
|
||||
def stop():
|
||||
body.remove_page("Web Radio")
|
||||
|
||||
def check_version():
|
||||
if libsaria.__major__ != 4:
|
||||
return False
|
||||
if libsaria.__minor__ == 4:
|
||||
return True
|
||||
return False
|
|
@ -1,135 +0,0 @@
|
|||
# Bryan Schumaker (11/13/2010)
|
||||
|
||||
import libsaria
|
||||
import imp
|
||||
from libsaria.sources import library
|
||||
from libsaria import threads
|
||||
from libsaria import lastfm
|
||||
|
||||
__NAME__ = "Web Server"
|
||||
|
||||
path = libsaria.path
|
||||
exists = path.exists
|
||||
join = path.join
|
||||
sep = path.sep
|
||||
basename = path.basename
|
||||
splitext = path.splitext
|
||||
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||
|
||||
html = join(path.cwd(), "html")
|
||||
server = None
|
||||
types = {".html":"text/html", ".js":"text/javascript",
|
||||
".ico":"image/vnd.microsoft.icon",
|
||||
".png":"image/png", ".jpg":"image/jpeg",
|
||||
".py":"text/html", ".mp3":"audio/mpeg",
|
||||
".ogg":"audio/ogg"}
|
||||
|
||||
|
||||
def format_text(text):
|
||||
text = text.replace("%20", " ")
|
||||
text = text.replace("%2F", "/")
|
||||
text = text.replace("%27", "'")
|
||||
text = text.replace("%2C", ",")
|
||||
return text
|
||||
|
||||
def format_path(path):
|
||||
if path == "" or path == "/":
|
||||
path = html + "/index.html"
|
||||
return path, None
|
||||
split = path.split("?", 1)
|
||||
if len(split) == 1:
|
||||
return html + path, None
|
||||
path = split[0]
|
||||
args = split[1].split("&")
|
||||
kwargs = {}
|
||||
for arg in args:
|
||||
split = arg.split("=", 1)
|
||||
kwargs[split[0]] = format_text(split[1])
|
||||
return html + path, kwargs
|
||||
|
||||
|
||||
class HTTPRequest(BaseHTTPRequestHandler):
|
||||
|
||||
def do_GET(self):
|
||||
try:
|
||||
fpath, args = format_path(self.path)
|
||||
#print fpath
|
||||
base, ext = splitext(fpath)
|
||||
if ext == ".py":
|
||||
self.py_file(args, fpath, base)
|
||||
elif ext == ".jpg":
|
||||
self.jpg_file(fpath)
|
||||
elif ext == ".mp3" or ext == ".ogg":
|
||||
self.audio_file()
|
||||
else:
|
||||
self.other_file(fpath, ext)
|
||||
except IOError:
|
||||
self.send_error(404, 'File Not Found: %s' % self.path)
|
||||
|
||||
def do_POST(self):
|
||||
print self.path
|
||||
print "Received a post request!"
|
||||
|
||||
def res_ok(self, ext):
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', '%s' % types[ext])
|
||||
self.end_headers()
|
||||
|
||||
def py_file(self, kw, path, base):
|
||||
if not exists(path):
|
||||
raise IOError
|
||||
file = basename(base)
|
||||
mod = imp.load_source(file, path)
|
||||
self.res_ok(".py")
|
||||
mod.to_html(self.wfile, kw)
|
||||
|
||||
def jpg_file(self, ipath):
|
||||
split = self.path.strip("/").split("/")
|
||||
if split[0] == "artwork":
|
||||
artist = format_text(split[1])
|
||||
album = splitext(split[2])[0]
|
||||
album = format_text(album)
|
||||
ipath = lastfm.get_artwork_tags(artist, album)
|
||||
base, ext = splitext(ipath)
|
||||
self.other_file(ipath, ext)
|
||||
|
||||
def audio_file(self):
|
||||
sid, ext = splitext(self.path.strip("/"))
|
||||
fpath = library.get_attrs(long(sid), "filepath")
|
||||
self.other_file(fpath, ext)
|
||||
|
||||
def other_file(self, path, ext):
|
||||
if not exists(path):
|
||||
raise IOError
|
||||
try:
|
||||
#print "Opening: %s" % path
|
||||
f = open(path)
|
||||
self.res_ok(ext)
|
||||
self.wfile.write(f.read())
|
||||
f.close()
|
||||
except Exception,e:
|
||||
print "Error!! message: %s" % e
|
||||
|
||||
|
||||
def start_server():
|
||||
global server
|
||||
if libsaria.__dev__ == True:
|
||||
server = HTTPServer(('', 4243), HTTPRequest)
|
||||
else:
|
||||
server = HTTPServer(('', 4242), HTTPRequest)
|
||||
server.serve_forever()
|
||||
|
||||
def start():
|
||||
threads.background(start_server)
|
||||
|
||||
def stop():
|
||||
server.shutdown()
|
||||
|
||||
def check_version():
|
||||
if libsaria.__major__ != 4:
|
||||
return False
|
||||
if libsaria.__minor__ == 4:
|
||||
return True
|
||||
return False
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
# Bryan Schumaker (10/30/2010)
|
||||
|
||||
import ocarina
|
||||
from ocarina import window
|
||||
gdk = ocarina.gdk
|
||||
libsaria = ocarina.libsaria
|
||||
get_attrs = libsaria.sources.get_attrs
|
||||
invite = libsaria.event.invite
|
||||
|
||||
__NAME__ = "Window Manager Tweaks"
|
||||
|
||||
|
||||
def tweak_icon(file):
|
||||
if file == None:
|
||||
file = "images/ocarina.png"
|
||||
gdk.threads_enter()
|
||||
window.set_icon(file)
|
||||
gdk.threads_leave()
|
||||
|
||||
def tweak_title(filepath):
|
||||
if filepath != None:
|
||||
title = get_attrs("title")
|
||||
else:
|
||||
title = ocarina.__vers__
|
||||
window.set_title(title)
|
||||
|
||||
def start():
|
||||
invite("POSTLOAD", tweak_title)
|
||||
invite("POSTGETART", tweak_icon)
|
||||
|
||||
def stop():
|
||||
pass
|
||||
|
||||
def check_version():
|
||||
if libsaria.__major__ != 4:
|
||||
return False
|
||||
if libsaria.__minor__ == 4:
|
||||
return True
|
||||
return False
|
|
@ -1,36 +0,0 @@
|
|||
# Bryan Schumaker (1 / 22 / 2010)
|
||||
# Use this script to check if all required and
|
||||
# optional dependencies have been installed
|
||||
|
||||
print "Checking for gstreamer"
|
||||
import gst
|
||||
|
||||
print "Checking for tagpy"
|
||||
import tagpy
|
||||
|
||||
print "Checking for gobject"
|
||||
import gobject
|
||||
|
||||
print "Checking for gtk"
|
||||
import gtk
|
||||
|
||||
print "Checking for pango"
|
||||
import pango
|
||||
|
||||
print ""
|
||||
print "==================="
|
||||
print "Basic checks passed"
|
||||
print "==================="
|
||||
print ""
|
||||
|
||||
warning = "WARNING: install %s to use the %s plugin"
|
||||
try:
|
||||
print "Checking for pynotify"
|
||||
import pynotify
|
||||
except:
|
||||
print warning % ("pynotify", "notify")
|
||||
|
||||
try:
|
||||
print "Checking for webkit"
|
||||
except:
|
||||
print warning % ("webkit", "web radio")
|
|
@ -1,36 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
PYTHONS=`find /usr/bin/python* | grep -v config | grep -v count`
|
||||
|
||||
function gen_ocarina()
|
||||
{
|
||||
PY=$1
|
||||
#OUT="bin/ocarina"
|
||||
#echo "#!/bin/bash" > $OUT
|
||||
#echo "$PY ocarina.py \$*" >> $OUT
|
||||
#chmod +x $OUT
|
||||
|
||||
OUT="ocarina.py"
|
||||
echo "#!$PY" > $OUT
|
||||
echo "import ocarina" >> $OUT
|
||||
echo "ocarina.run()" >> $OUT
|
||||
chmod +x $OUT
|
||||
}
|
||||
|
||||
function gen_bin()
|
||||
{
|
||||
PY=$1
|
||||
gen_ocarina $PY
|
||||
echo ""
|
||||
}
|
||||
|
||||
for PY in $PYTHONS
|
||||
do
|
||||
$PY -c "import gst" 2>/dev/null 1>/dev/null
|
||||
if [ "$?" == "0" ]
|
||||
then
|
||||
echo "Found python version: $PY"
|
||||
gen_bin $PY
|
||||
break
|
||||
fi
|
||||
done
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
if [ $# != 1]
|
||||
then
|
||||
echo "Usage: scripts/new_release BRANCH_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NAME=$1
|
||||
echo "Creating new release: $NAME"
|
||||
|
||||
git push origin origin:refs/heads/$NAME
|
||||
git fetch origin
|
||||
git checkout --track -b $NAME origin/$NAME
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/bash
|
||||
if [ $# != 1 ]
|
||||
then
|
||||
echo "Usage: scripts/tag TAG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git tag -a $1
|