changeset 3255:3c3a3f3c2269

- Added my "Locate and Play" script to contrib. - Added a few commented-out lines to my G15 LCD script to help anyone who wants to tweak it.
author "Stephan Sokolow <http://www.ssokolow.com/ContactMe>"
date Sun, 05 Aug 2007 21:26:56 -0400
parents 4f4e07f06801
children 80c31427ec95
files contrib/g15_audacious.py contrib/lap.py
diffstat 2 files changed, 130 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/contrib/g15_audacious.py	Sun Aug 05 20:20:19 2007 -0500
+++ b/contrib/g15_audacious.py	Sun Aug 05 21:26:56 2007 -0400
@@ -10,6 +10,7 @@
 - Every second update should skip the D-Bus calls. They are the biggest CPU drain.
   (I also only use a half-second update interval for the scroller. Feel free to 
    turn it off and use a 1-second interval.
+- Wipe and redraw the entire screen at songchange. I'm not sure why yet, but some songs can cause mess-ups.
 - Clean up this quick hack of a script.
 
 Notes for people hacking this script:
@@ -34,6 +35,11 @@
 "0110000" +
 "0100000" )
 
+# 3x5 "Characters" (Icon glyphs sized to match the Small font)
+CHAR_S_NOTE = "011010010110110"
+CHAR_S_HALFTONE = "101010101010101"
+CHAR_S_CROSS = "000010111010000"
+
 # I prefer no icon when it's playing, so overwrite the play icon with a blank.
 ICN_PLAY = '0' * ICON_DIMS[0] * ICON_DIMS[1]
 
@@ -109,6 +115,11 @@
 			msg_handle.write('PB 0 9 160 14 0 1 1\n') # Wipe away any remnants of the old title that wouldn't be overwritten.
 			msg_handle.write('TO 0 9 0 0 "%s"\n' % titleString)
 
+			# Uncomment to place a note in the gap where the scroller wraps around
+			#notePos = (len(titleString) - scrollPivot - 1) * 4
+			#if len(titleString) > 40 and notePos <= 156:
+			#	msg_handle.write('PO %d 9 3 5 "%s"\n' % (notePos, CHAR_S_NOTE))
+
 			# Volume bar
 			msg_handle.write('DB 29 28 159 29 1 %d 100 1\n' % ((volume[0] + volume[1])/2))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/lap.py	Sun Aug 05 21:26:56 2007 -0400
@@ -0,0 +1,119 @@
+#!/usr/bin/env python
+"""Locate and Play
+Author: Stephan Sokolow (deitarion/SSokolow)
+License: GNU GPL-2
+Version: 1.0
+
+Description:
+- A quick wrapper to make playing songs via the local command quick and easy.
+- Works with any player which implements the MPRIS standard for remote control via D-Bus.
+- Accepts multiple space- and/or comma-separated choices after presenting the results.
+- Can enqueue or enqueue and play.
+- Can show full paths or just filenames.
+- Will behave in a sane fashion when asked to enqueue and play multiple files.
+
+TODO: 
+ - Complete the list of extensions for ModPlug, Embedded MPlayer (plugins-ugly), and UADE (3rd-party)
+ - Support sticking a 'q' in the result to choose enqueue on the fly
+ - Support an "all" keyword and an alternative to Ctrl+C for cancelling. (maybe 0)
+"""
+
+ADLIB_EXTS    = ['.a2m', '.adl',  '.adlib', '.amd', '.bam', '.cff', '.cmf', '.d00', '.dfm',  '.dmo', '.dro', '.dtm', '.hsc', '.hsp',
+                 '.jbm', '.ksm',  '.laa',   '.lds', '.m',   '.mad', '.mkj', '.msc', '.mtk',  '.rad', '.raw', '.rix', '.rol', '.sat', 
+                 '.sa2', '.sci',  '.sng',   '.imf', '.wlf', '.xad', '.xsm']
+CONSOLE_EXTS  = ['.adx', '.ay',   '.gbs',   '.gym', '.hes', '.kss', '.minipsf',     '.nsf', '.nsfe', '.psf', '.sap', '.sid', '.spc', 
+                 '.vgm', '.vgz',  '.vtx',   '.ym']
+MIDI_EXTS     = ['.mid', '.midi', '.rmi']
+MODULE_EXTS   = [ '.it', ',mod',  '.s3m',   '.stm', '.xm']
+PLAYLIST_EXTS = ['.cue', '.m3u',  '.pls',   '.xspf']
+WAVEFORM_EXTS = ['.aac', '.aif',  '.aiff',  '.au', '.flac', '.m4a', '.mp2', '.mp3', '.mpc', '.ogg', '.snd', '.tta', '.voc', '.wav', 
+                 '.wma', '.wv']
+
+# Edit these lines to choose the kind of files to be filtered for. By default, playlist extensions are excluded.
+OK_EXTS = WAVEFORM_EXTS + MODULE_EXTS + CONSOLE_EXTS + MIDI_EXTS + ADLIB_EXTS
+# If you want true format filtering, YOU write the mimetype cache.
+USE_PAGER = False  # Should we page output if it's more than a screenful?
+
+locate_command = ['locate', '-i']
+
+# ========== Configuration Ends ==========
+
+import fnmatch, optparse, os, subprocess
+from dbus import Bus, DBusException
+
+# Use readline if available but don't depend on it
+try: import readline
+except ImportError: pass
+
+# connect to DBus
+bus = Bus(Bus.TYPE_SESSION)
+
+def get_results(query):
+	"""Given a query or series of queries for the locate command, run them."""
+	results, cmd = [], locate_command + (isinstance(query, basestring) and [query] or query)
+	for line in subprocess.Popen(cmd, stdout=subprocess.PIPE).stdout:
+		result = line.strip()
+		if os.path.splitext(result)[1] in OK_EXTS:
+			results.append(result)
+	results.sort()
+	return results
+
+def filter(results, filters):
+	for filter in filters:
+		results = [x for x in results if fnmatch.fnmatch(x.lower(), '*%s*' % filter.lower())]
+	return results
+
+def makeMenu(results, strip_path=True):
+	for pos, val in enumerate(results):
+		val = strip_path and os.path.split(val)[1] or val
+		print "%3d) %s" % (pos+1, val)
+
+def addTrack(path, play=False):
+	try:
+		mp = bus.get_object('org.freedesktop.MediaPlayer', '/TrackList')
+		mp.AddTrack('file://' + path, play)
+	except DBusException:
+		print "ERROR: Unable to contact media player."
+
+def parseChoice(inString):
+	try:
+		return [int(inString)]
+	except ValueError:
+		choices = []
+		for x in inString.replace(',',' ').split():
+			try: choices.append(int(x))
+			except ValueError: print "Not an integer: %s" % x
+		return choices
+
+if __name__ == '__main__':
+    try:
+	op = optparse.OptionParser()
+	op.add_option("-q", "--enqueue", action="store_true", dest="enqueue", default=False,
+	               help="Don't start the song playing after enqueueing it.")
+	op.add_option("-p", "--show_path", action="store_true", dest="show_path", default=False,
+	               help="Show the full path to each result.")
+
+	(opts, args) = op.parse_args()
+	
+	results = (len(args) > 0) and get_results(args.pop(0)) or []
+	results = filter(results, args)
+
+	def takeChoice(index, play=False):
+		index = index - 1
+		if index >= 0 and index < len(results):
+			addTrack(results[index], play)
+		else:
+			print "Invalid result index: %s" % (index + 1)
+
+	if len(results):
+		makeMenu(results, not opts.show_path)
+		choices = parseChoice(raw_input("Choice(s) (Ctrl+C to cancel): "))
+
+		if len(choices):
+			takeChoice(choices.pop(0), not opts.enqueue)
+		for item in choices:
+			takeChoice(item, False) # This ensures proper behaviour with no --enqueue and multiple choices.
+	else:
+		print "No Results"
+    except KeyboardInterrupt:
+	pass