| Line | Revision | Contents |
| 1 | 39 | #!/usr/bin/env python |
| 2 | # -*- coding: utf-8 -*- |
|
| 3 | 57 | """mediatomb-sirius.py (c) 2007 ... 2009 Matthew Ernisse <mernisse@ub3rgeek.net> |
| 4 | 39 | All Rights Reserved. |
| 5 | ||
| 6 | 57 | $Id: mediatomb-sirius.py,v 1.9 2008/12/22 02:45:38 mernisse Exp $ |
| 7 | 39 | |
| 8 | Transcode Sirius Internet Radio streams, originally written to allow Mediatomb |
|
| 9 | to playback Sirius Radio. |
|
| 10 | ||
| 11 | Requires: |
|
| 12 | vlc (http://www.videolan.org/vlc/) - could probably be modified to work |
|
| 13 | with ffmpeg or mencoder, but vlc has pretty decent URL handling and it |
|
| 14 | is universally available. |
|
| 15 | ||
| 16 | Sipie (http://sipie.sourceforge.net/) - Python backend for Sirius |
|
| 17 | streams. |
|
| 18 | ||
| 19 | Configuration: |
|
| 20 | Once you have Sipie up and working this should function automatically, |
|
| 21 | it loads your Sipie config from $HOME/.sipie/ |
|
| 22 | ||
| 23 | License: |
|
| 24 | If you find this useful, I'd love to hear from you. |
|
| 25 | ||
| 26 | Redistribution and use in source and binary forms, |
|
| 27 | with or without modification, are permitted provided |
|
| 28 | that the following conditions are met: |
|
| 29 | ||
| 30 | * Redistributions of source code must retain the |
|
| 31 | above copyright notice, this list of conditions |
|
| 32 | and the following disclaimer. |
|
| 33 | * Redistributions in binary form must reproduce |
|
| 34 | the above copyright notice, this list of conditions |
|
| 35 | and the following disclaimer in the documentation |
|
| 36 | and/or other materials provided with the distribution. |
|
| 37 | ||
| 38 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 39 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 40 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
|
| 41 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
| 42 | COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
|
| 43 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
|
| 44 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS |
|
| 45 | OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|
| 46 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR |
|
| 47 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
|
| 48 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
| 49 | ||
| 50 | """ |
|
| 51 | import os |
|
| 52 | 46 | import re |
| 53 | 47 | import signal |
| 54 | import subprocess |
|
| 55 | 39 | import sys |
| 56 | import Sipie |
|
| 57 | 46 | import urllib2 |
| 58 | 39 | |
| 59 | from sys import exit |
|
| 60 | ||
| 61 | 47 | PLAYFD = None |
| 62 | FIFOFD = None |
|
| 63 | ||
| 64 | 39 | def findPlayer(exe): |
| 65 | """ Returns the Path to the requested executable by searching the |
|
| 66 | ||
| 67 | user's PATH environment variable. |
|
| 68 | ||
| 69 | Arguments: |
|
| 70 | exe - string, file to search for |
|
| 71 | Returns: |
|
| 72 | None or string |
|
| 73 | ||
| 74 | """ |
|
| 75 | for e in os.environ['PATH'].split(':'):
|
|
| 76 | if os.path.exists(e + "/" + exe): |
|
| 77 | return e + "/" + exe |
|
| 78 | return None |
|
| 79 | ||
| 80 | 44 | def Usage(): |
| 81 | print """Usage: %s [list][create][playlist fifo] |
|
| 82 | ||
| 83 | Viewing or creating stream list: |
|
| 84 | list - Prints the available streams to stdout |
|
| 85 | create - creates playlist files in the current directory |
|
| 86 | ||
| 87 | Playing: |
|
| 88 | The arguments= list in the Mediatomb config should just be |
|
| 89 | "%%in %%out". This will pass the playlist file as the first |
|
| 90 | argument and the FIFO as the second argument. For testing |
|
| 91 | you can manually pass those arguments yourself. |
|
| 92 | """ % sys.argv[0] |
|
| 93 | exit(2) |
|
| 94 | ||
| 95 | 47 | def sig_cleanup(sig, stack): |
| 96 | global FIFOFD, PLAYFD |
|
| 97 | os.kill(PLAYFD.pid, 15) |
|
| 98 | exit(0) |
|
| 99 | ||
| 100 | 57 | def playVLC(player, url, fifo): |
| 101 | global FIFOFD, PLAYFD |
|
| 102 | ||
| 103 | # vlc is shameful, in that it opens the fifo prior to |
|
| 104 | # actually starting the stream, so mediatomb thinks the |
|
| 105 | # transcoder died and then kills the process. |
|
| 106 | # NOTE NOTE NOTE NOTE NOTE |
|
| 107 | # The PS3 is BIG ENDIAN, because it's based on the PPC arch, |
|
| 108 | # so make sure we output BIG ENDIAN lpcm, not LITTLE ENDIAN, |
|
| 109 | # unless you love static A LOT |
|
| 110 | args = '"%s" -I dummy --http-user-agent="NSPlayer" ' % (url) |
|
| 111 | args += '--sout "#transcode{acodec=s16be,channels=2,samplerate=44100}'
|
|
| 112 | args += ':std{access=file,mux=wav,dst=-}"'
|
|
| 113 | ||
| 114 | # catch the kill signal from sipie so we can kill off VLC |
|
| 115 | # otherwise it could very well just sit there forever like |
|
| 116 | # a pain in the arse. |
|
| 117 | signal.signal(signal.SIGTERM, sig_cleanup) |
|
| 118 | signal.signal(signal.SIGHUP, sig_cleanup) |
|
| 119 | ||
| 120 | FIFOFD = open(fifo, 'w') |
|
| 121 | PLAYFD = subprocess.Popen("%s %s" % (player, args), shell=True,
|
|
| 122 | stdout=subprocess.PIPE) |
|
| 123 | ||
| 124 | for line in PLAYFD.stdout: |
|
| 125 | try: |
|
| 126 | FIFOFD.write(line) |
|
| 127 | except: |
|
| 128 | FIFOFD.close() |
|
| 129 | exit(0) |
|
| 130 | exit(0) |
|
| 131 | ||
| 132 | def playMplayer(player, url, fifo): |
|
| 133 | args = ['mplayer', '-nocache', '-user-agent', 'NSPlayer', \ |
|
| 134 | '-ao', 'null', '-dumpaudio', '-dumpfile', '%s' % (fifo), url] |
|
| 135 | ||
| 136 | os.execvp(player, args) |
|
| 137 | exit(0) |
|
| 138 | ||
| 139 | 39 | def main(): |
| 140 | """ This uses Sipie to transcode the asx streams from Sirius Internet |
|
| 141 | ||
| 142 | Radio to mp3, useful for streaming to a media renderer. |
|
| 143 | ||
| 144 | Arguments: |
|
| 145 | 45 | argv[1] - Sirius stream name, or (list|create). If list it |
| 146 | will output a list of streams available. If create it will |
|
| 147 | populate the current directory with .sirius files for each |
|
| 148 | stream available. |
|
| 149 | 39 | |
| 150 | argv[2] - Output File / FIFO. |
|
| 151 | ||
| 152 | Returns: |
|
| 153 | Nothing. |
|
| 154 | ||
| 155 | Exit Values: |
|
| 156 | 0 - success |
|
| 157 | 1 - failure |
|
| 158 | 2 - usage error |
|
| 159 | ||
| 160 | """ |
|
| 161 | 45 | if not os.path.exists(os.environ['HOME'] + '/.sipie/'): |
| 162 | print """ERROR: You must configure Sipie prior to running %s |
|
| 163 | You can do this by running sipie.py from the distribution's directory and |
|
| 164 | answering the questions. Please also ensure you complete the CAPCHA.""" % ( |
|
| 165 | sys.argv[0] ) |
|
| 166 | exit(1) |
|
| 167 | ||
| 168 | 44 | if len(sys.argv) == 1: |
| 169 | Usage() |
|
| 170 | 39 | |
| 171 | if len(sys.argv[1:]) < 2: |
|
| 172 | 45 | config = Sipie.Config(os.environ['HOME'] + '/.sipie/') |
| 173 | sipie = Sipie.Factory(config.items()) |
|
| 174 | ||
| 175 | 44 | if sys.argv[1] == "list": |
| 176 | print "Available Streams:" |
|
| 177 | for stream in sipie.getStreams(): |
|
| 178 | print " %s" % (stream) |
|
| 179 | exit(0) |
|
| 180 | 45 | |
| 181 | 44 | elif sys.argv[1] == "create": |
| 182 | print "Creating playlists" |
|
| 183 | for stream in sipie.getStreams(): |
|
| 184 | fd = open("%s.sirius" % (stream), 'w')
|
|
| 185 | fd.close() |
|
| 186 | exit(0) |
|
| 187 | 45 | |
| 188 | 44 | else: |
| 189 | Usage() |
|
| 190 | 39 | |
| 191 | stream = os.path.basename(sys.argv[1].split(".")[0])
|
|
| 192 | fifo = sys.argv[2].strip() |
|
| 193 | ||
| 194 | config = Sipie.Config(os.environ['HOME'] + '/.sipie/') |
|
| 195 | sipie = Sipie.Factory(config.items()) |
|
| 196 | ||
| 197 | if not stream in sipie.getStreams(): |
|
| 198 | print "%s not found in getStreams()" % (stream) |
|
| 199 | exit(1) |
|
| 200 | 46 | |
| 201 | 39 | sipie.setStream(stream) |
| 202 | 46 | |
| 203 | 57 | player = findPlayer('mplayer')
|
| 204 | player = None |
|
| 205 | if not player: |
|
| 206 | player = findPlayer('vlc')
|
|
| 207 | if not player: |
|
| 208 | print "Cannot find mplayer or vlc in your PATH" |
|
| 209 | exit(1) |
|
| 210 | else: |
|
| 211 | playVLC(player, sipie.asxURL, fifo) |
|
| 212 | else: |
|
| 213 | playMplayer(player, sipie.asxURL, fifo) |
|
| 214 | ||
| 215 | 39 | |
| 216 | if __name__ == "__main__": |
|
| 217 | main() |
Loggerhead 1.17 is a web-based interface for Bazaar branches