SourceForge.net Logo

Raagplay

Raagplay

Introduction
Operation
Platforms supported
Preferences
Playlists
    Specification
    
Generation
Interaction with Players
Download and Install
Future
Known Issues
FAQ

Introduction

When you have large collection of MP3s, it is very difficult to play and manage them only with media player. You need software that can manage this collection and that can intelligently pick up songs to play. While I have not really tried available software in this regard (like iTunes for example), I am fairly sure that no such programs are available that meet my criteria. The things I would like to do include: So I wrote one such program myself. As you will see, it will do all the things listed above and it is fairly easy to extend. I must point out that there is no GUI and this tool is completely command line based.

Operation

Usage:

raagplay.py [--help] [--cfgdir <cfgdir>] --pl <playlist_name> ...

--help: print this message and exit.
--cfgdir <cfgdir>: <cfgdir> should be absolute path to config directory.
	This is where all playlists files and history are located. Note that
	this value can also be specified using a preference.
--pl <playlist_name>: playlist name.
When it comes up, raagplay does the following for each playlist: This is done for each playlist file. Then, it spawns a thread that plays a song from each list in round-robin fashion. When all the entries in a list are exhausted, the history file is renamed with ".old" extension. If "repeat_play" option is set (which is default), the internal list is again populated from playlist file resulting in whole list being used for playing again (from next iteration). history is maintained in a file named <cfgdir>/history/<listname>.txt. raagplay puts debugging and informational messages in a log file named <cfgdir>/<hostname>_implog.txt.

While a thread is playing songs, another thread in raagplay presents a shell like interface to the user. The following commands are supported from this shell. Please note that not all commands work on all supported platforms in the same way. Please see Known Issues section for more details.

Platforms supported

Since it is written in pure python, it should run on any platform that python can run on. . However, this was only tested on windows and linux. Few lines of code will need to be added for other platforms. Primarily to recognize and use a standard name for the OS. There should be no changes required functionality-wise.

Preferences

All preferences to raagplay are set in src/impprefs.py. The syntax should be python syntax. The preference variables can have "qualifiers". The current list of qualifiers include list name, hostname, and os name (win or linux).

For example, when raagplay needs to find out the value of the preference "repeat_play" for list "hlist2" on hostname "vennela" running windows, it looks for following variables:

repeat_play_hlist2_vennela_win
repeat_play_hlist2_vennela
repeat_play_hlist2_win
repeat_play_vennela_win
repeat_play_vennela
repeat_play_win
repeat_play
in that order. It will stop at the first variable that it finds. This scheme would allow us to set preferences in a flexible fashion. Note that list name is used as a qualifier only for those preferences which are playlist specific. For example, "user_hist" is playlist specific while "default_rootdirs" is not. So "default_rootdirs" will only have following combinations:
default_rootdirs_vennela_win
default_rootdirs_vennela
default_rootdirs_win
default_rootdirs
The following are the preferences currently recognized:

Playlists

Specification

Playlists are nothing but text files with list of song files. But there are multiple ways in which a file names can be specified. Assume a playlist named "testlist":

Type 1:

E:/music/movie1/song1.mp3
E:/music/movie1/song2.mp3
E:/music/movie2/song1.mp3
E:/music/movie2/song2.mp3
In this list, all the files have absolute path. In general this is not preferable as specifying absolute path prevents the same list being used on different systems.

Type 2:

music/movie1/song1.mp3
music/movie1/song2.mp3
music/movie2/song1.mp3
music/movie2/song2.mp3
This is the same list of songs as in Type 1 but the paths are not absolute. The only issue here is how to convert a path in this list to the actual file system path that can be located. For this purpose, raagplay computes "commonprefix" for each list. For this list, "commonprefix" is "music/". It needs to find out where is this located. This location can be spefied using the preference "rootdir". For example, "testlist_rootdir" can be set to "E:". Impayer will prepend this rootdir to each path in the list thus forming the absolute path. But as the number of lists grows, it becomes tedious to have this preference for each list. So there is another preference variable called "default_rootdirs". This is list of rootdirs. eg,
default_rootdirs = [ "E:", "E:/music", "H:" ]
If raagplay cannot find "rootdir" for a given list, it will try each of the items in the list "default_rootdirs". It will stop at the first entry where <item>+"/"+commonprefix exists. So whenever a playlist is created, just make sure the rootdir is added to this list. The assumption is that this list will be relatively small with each entry good for multiple lists. If you have large number of entries in this list, you may want to reorganize your collection into a better hierarchy.

Type 3:

movie1/song1.mp3
movie1/song2.mp3
movie2/song1.mp3
movie2/song2.mp3
In this case, there is no "commonprefix". So raagplay will try to find out "rootdir" for each song from default_rootdirs.

It is preferrred to use "Type 2" or "Type 3" as they help in playlist "portability" across systems. For example, if you mount E: drive at /e_drive on a linux system, you canstill use Type 2 playlist but not Type 1.

Generation

Since playlists are nothing but text files with paths to song files, several options exist for creating the lists. The easiest approach is to use "find" command. If you have cygwin, you can do following:
$ cd E:
$ find music -iname "*.mp3" > <cfgdir>/testlist.txt
<cfgdir>/testlist.txt will have something like
music/movie1/song1.mp3
music/movie1/song2.mp3
music/movie2/song1.mp3
music/movie2/song2.mp3
There is another more sophisticated method to generate playlist files. You can have an XML file, say, named "songsdb.xml". Its content can be something like:

<songs>
		<song lang="telugu" melody="1"
				path="music/movie1/song1.mp3" 
		/>
		<song lang="telugu"
				path="music/movie1/song2.mp3" 
		/>
		<song lang="telugu" 
				path="music/movie2/song1.mp3" 
		/>
		<song lang="telugu" melody="1"
				path="music/movie2/song2.mp3" 
		/>
</songs>
You can then have another file with the following XSLT code:

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" />

<xsl:template match="/" >
    <xsl:for-each select="songs/song[@lang='telugu' and @melody='1']">
        <xsl:value-of select="@path"/>
        <xsl:text>
</xsl:text>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

With these two files, you can use any XSLT processor to generate playlists. I use 4xslt (part of 4Suite from Fourthought.com) but any XSLT processor should do the job.

$ 4xslt -o <cfgdir>/tlist.txt songsdb.xml tmelody.xsl

<cfgdir>/tlist.txt will contain telugu melody songs:

music/movie1/song1.mp3
music/movie2/song2.mp3
You can have one XSLT file for each list. This way, you can have any number of attributes for each song and generate playlists based on attributes. But it will be very tedious to add possibly thousands of songs to this file manually. Unfortunately, there is no automated way of doing this at present but I am sure there will be one sometime in the future. Until there is one, it is convenient to use a combination of above two methonds. For example, I use "find" to create big generic lists and if I hear a song that I think should have some attributes, I simply use "a" command to remember it and later when I have time, add it to the XML file. This process can be done incrementally as time permits and with time, you will build a good songsdb.xml.

Interaction with Players

raagplay requires that the actualy player program support an option to exit after playing a song. I use realplayer on Linux which supports "-q" for this purpose (version 10 or later). On windows, realplayer doesn't support this option so I could not use it. Instead, I use "yPlay". This didn't have any such option to start with but the developer of this program kindly added "--exit" at my request. Note that when yPlay comes up for the very first time after installation, a window pops up with some queries. Just press OK and everything should be fine.

Download and Install

Future

You can check current proposals here.

Known Issues