#!/usr/bin/python3
from http.server import BaseHTTPRequestHandler, HTTPServer
import io
import gi
gi.require_version('Gst', '1.0')
from gi.repository import GObject, Gst
import time
import requests

Gst.init(None)
mainloop = GObject.MainLoop()

hostName = "0.0.0.0"
serverPort = 8123

class AACToMP3Stream( BaseHTTPRequestHandler ):

    def stop_pipeline( self ):
        Gst.debug_bin_to_dot_file( self.pipeline, Gst.DebugGraphDetails.ALL, 'stream' )
        self.pipeline.set_state( Gst.State.PAUSED )
        self.src.set_state( Gst.State.PAUSED )
        self.pipeline.set_state( Gst.State.NULL )
        self.src.set_state( Gst.State.NULL )
        self.pipeline.remove( self.src )


    def do_GET( self ):
        self.send_response( 200 )
        self.send_header("Content-type", "audio/mpeg")

        self.end_headers()

        # Gstreamer doesn't like redirects all that much. It will leave a socket
        # open to the original address and only close the socket for the redirected
        # address. So we resolve the redirect ourselves.
        url = 'http://live.streams.klassikradio.de/klassikradio-deutschland'
        print( "Checking stream URL" )
        resp = requests.head( url, allow_redirects=False )
        while( resp.status_code == 300 or resp.status_code == 302 ):
            url = resp.headers['Location']
            print( "Redirected to " + url )
            resp = requests.head( url, allow_redirects=False )

        ua = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17"

        pipeline_command = [
            'souphttpsrc',
                'user-agent="' + ua +'"',
                'location="' + url + '"',
                'name=src',
                '!',
            'icydemux', '!',
            'faad', '!',
            'lamemp3enc',
                'quality=2',
                'target=bitrate',
                'bitrate=128',
                'cbr=true',
                '!',
            'id3mux', '!',
            #'autoaudiosink',
            'appsink',
                'name=app',
                'max_buffers=2',
                'drop=true',
                'emit-signals=true',
                'sync=true',
        ]
        command = " ".join( pipeline_command )
        self.pipeline = Gst.parse_launch(command)
        self.app = self.pipeline.get_by_name( 'app' )
        self.src = self.pipeline.get_by_name( 'src' )

        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()

        self.pipeline.set_state( Gst.State.PAUSED )
        print( "Pipeline Ready: PAUSED" )


        try:
            def on_new_buffer( sink ):
                sample = sink.emit( "pull-sample" )
                buf = sample.get_buffer()

                (result, mapinfo) = buf.map( Gst.MapFlags.READ )
                assert result

                try:
                    self.wfile.write( mapinfo.data )
                    pass

                except:
                    print( "Stop pipe, no more clients?" )
                    mainloop.quit()

                    return Gst.FlowReturn.EOS

                finally:
                    buf.unmap( mapinfo )

                return Gst.FlowReturn.OK

            def on_message(bus, message):
                if message.type == Gst.MessageType.EOS:
                    print( "Bus EOS" )
                    mainloop.quit()

                    return Gst.FlowReturn.EOS

            self.bus.connect( "message", on_message )
            self.app.connect( 'new-sample', on_new_buffer )

            print( "Pipeline Ready: PLAYING" )
            self.pipeline.set_state( Gst.State.PLAYING )
            mainloop.run()


            self.stop_pipeline()
            del self.pipeline

            self.wfile.flush()

#            self.finish()
#            self.connection.close()
            print( "Connection closed" )


        except KeyboardInterrupt:
            return

if __name__ == "__main__":
    webServer = HTTPServer((hostName, serverPort), AACToMP3Stream )
    print("Server started http://%s:%s" % (hostName, serverPort))

    try:
        webServer.serve_forever()
    except KeyboardInterrupt:
        pass

    webServer.server_close()
    print("Server stopped.")

