import socket
import gst
import gobject
import thread
import threading
import time
PORT=3333
STATIONS={'fm4':'mms://stream1.orf.at/fm4_live',
'bayern2':'mms://gffstream-w3a.wm.llnwd.net/gffstream_w3a',
'bayern5':'mms://gffstream-w9b.wm.llnwd.net/gffstream_w9b'}
SOURCES={'mms://': 'mmssrc location={X}',
'http://': 'gnomevfssrc location={x}'}
ENCODERS={'mp3': { 'gst': 'lame', 'mime': 'audio/mpeg'}}
def close_pipe():
global gst_pipe
if gst_pipe:
gst_pipe.set_state(gst.STATE_NULL)
gst_pipe=None
def create_pipe(request, sock):
#request looks like
#/stationame.encoder, currently only encoders with 3 letters are supported
close_pipe()
global gst_pipe
source=None
encoder=None
# find station souce
if request[1:-4] in STATIONS:
for src_prefix in SOURCES:
if STATIONS[request[1:-4]][0:len(src_prefix)] == src_prefix:
source = SOURCES[src_prefix].replace('{X}', STATIONS[request[1:-4]])
break
# find encoder
if request[-3:] in ENCODERS:
encoder=ENCODERS[request[-3:]]['gst']
if encoder and source:
gst_pipe = gst.parse_launch(source + " ! decodebin ! " + encoder + " ! fdsink name=fd_sink")
gst_pipe.get_by_name('fd_sink').set_property('fd', sock.makefile('wb').fileno())
bus = gst_pipe.get_bus()
bus.add_signal_watch()
bus.connect('message', gstreamer_message)
return ENCODERS[request[-3:]]['mime']
def handle_request(client_sock):
req = ""
while True:
data = client_sock.recv(1)
if data == "":
break
req = req + data
if req[-4:] == "\r\n\r\n":
break
req = req.split('\r\n')
mime = create_pipe(req[0].split()[1], client_sock)
if mime:
client_sock.sendall("HTTP/1.1 200 OK\r\n");
client_sock.sendall("Content-Type: "+ mime +"\r\n")
client_sock.sendall("Cache-Control: no-cache, must-revalidate\r\n");
client_sock.sendall("\r\n\r\n")
#start playing till eos or client close
global transfer_event, gst_pipe
gst_pipe.set_state(gst.STATE_PLAYING)
transfer_event.clear()
transfer_event.wait()
close_pipe()
else:
#create playlist
# Try to find host
host = None
for line in req:
if line[0:4].lower() == 'host':
host = line[6:]
if not host:
host = 'localhost:' + PORT
playlist = ''
for station in STATIONS:
for encoder in ENCODERS:
playlist += 'http://' + host + '/' + station + '.' + encoder + '\r\n'
client_sock.sendall("HTTP/1.1 200 OK\r\n");
client_sock.sendall("Content-Type: audio/x-mpegurl\r\n")
client_sock.sendall("Content-Length: " + str(len(playlist)) + "\r\n")
client_sock.sendall('Content-Disposition: attachment; filename="playlist.m3u"\r\n')
client_sock.sendall("Cache-Control: no-cache, must-revalidate\r\n");
client_sock.sendall("\r\n\r\n")
client_sock.sendall(playlist)
def gstreamer_message(bus, message):
if message.type == gst.MESSAGE_ERROR or message.type == gst.MESSAGE_EOS:
global transfer_event
transfer_event.set()
def run_webserver():
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('', PORT))
sock.listen(1)
try:
while 1:
( clientsock, client ) = sock.accept()
handle_request ( clientsock )
clientsock.close()
finally:
sock.close()
if __name__=='__main__':
gobject.threads_init()
ws = thread.start_new_thread(run_webserver, ())
gst_pipe=None
transfer_event=threading.Event()
try:
gobject.MainLoop().run()
except KeyboardInterrupt:
close_pipe()
print "bye"