Пример #1
0
    def channel_metadata(self, channel_number, rewind=0):
        channel_number = int(channel_number)
        rewind = int(rewind)

        if channel_number not in self.sbe.sxm.lineup:
            return self.file_not_found()

        channel = self.sbe.sxm.lineup[channel_number]
        channel_id = str(channel['channelKey'])
        packet = next(self.sbe.sxm.packet_generator(channel_id, rewind))
        metadata = None

        for pes_packet in mpegutils.parse_transport_stream(packet):
            if pes_packet['pid'] == 1024:
                for es_packet in mpegutils.parse_packetized_elementary_stream(pes_packet['payload']):
                    new_meta = mpegutils.parse_sxm_metadata(es_packet['payload'])
                    if not metadata and new_meta:
                        metadata = new_meta

        response = json.dumps({
            'channel': channel,
            'nowplaying': {
                'artist': metadata[1],
                'title': metadata[0],
                'album': metadata[2],
            },
        }, sort_keys=True, indent=4).encode('utf-8')

        self.send_standard_headers(len(response), {
            'Content-type': 'application/json',
        })

        self.wfile.write(response)
Пример #2
0
    def channel_metadata(self, channel_number, rewind=0):
        channel_number = int(channel_number)
        rewind = int(rewind)

        if channel_number not in self.sbe.sxm.lineup:
            return self.file_not_found()

        channel = self.sbe.sxm.lineup[channel_number]
        channel_id = str(channel['channelKey'])
        packet = next(self.sbe.sxm.packet_generator(channel_id, rewind))
        metadata = None

        for pes_packet in mpegutils.parse_transport_stream(packet):
            if pes_packet['pid'] == 1024:
                for es_packet in mpegutils.parse_packetized_elementary_stream(
                        pes_packet['payload']):
                    new_meta = mpegutils.parse_sxm_metadata(
                        es_packet['payload'])
                    if not metadata and new_meta:
                        metadata = new_meta

        response = json.dumps(
            {
                'channel': channel,
                'nowplaying': {
                    'artist': metadata[1],
                    'title': metadata[0],
                    'album': metadata[2],
                },
            },
            sort_keys=True,
            indent=4).encode('utf-8')

        self.send_standard_headers(len(response), {
            'Content-type': 'application/json',
        })

        self.wfile.write(response)
Пример #3
0
    def channel_stream(self, channel_number, rewind=0):
        channel_number = int(channel_number)
        rewind = int(rewind)

        if channel_number not in self.sbe.sxm.lineup:
            return self.file_not_found()

        channel = self.sbe.sxm.lineup[channel_number]
        url = 'http://{}:{}/'.format(self.sbe.config('hostname'), self.sbe.config('port'))

        logging.info('Streaming: Channel #{} "{}" with rewind {}'.format(
            channel_number,
            channel['name'],
            rewind))

        self.protocol_version = 'ICY' # if we don't pretend to be shoutcast, doctors HATE us
        self.send_response_only(200)
        self.send_header('Content-type', 'audio/aacp')
        self.send_header('icy-br', '64')
        self.send_header('icy-name', channel['name'])
        self.send_header('icy-genre', channel['genre'])
        self.send_header('icy-url', url)
        self.send_header('icy-metaint', '32768')
        self.end_headers()

        channel_id = str(channel['channelKey'])
        track_title = ''
        start_time = None
        new_meta = False

        audio = bytearray()
        for ts_packet in self.sbe.sxm.packet_generator(channel_id, rewind):
            pes_streams = collections.defaultdict(bytearray)
            for pes_packet in mpegutils.parse_transport_stream(ts_packet):
                if 'payload' in pes_packet:
                    pes_streams[pes_packet['pid']].extend(pes_packet['payload'])

            for pid, pes_stream in pes_streams.items():
                for es_packet in mpegutils.parse_packetized_elementary_stream(pes_stream):
                    if pid == 768:
                        audio.extend(es_packet['payload'])
                    elif pid == 1024:
                        metadata = mpegutils.parse_sxm_metadata(es_packet['payload'])
                        if metadata:
                            new_title = '{} - {}'.format(metadata[1], metadata[0])
                            if new_title != track_title:
                                logging.info("Now playing: " + new_title)
                                track_title = new_title
                                new_meta = True

                    if len(audio) >= 32768:
                        if new_meta:
                            meta_title = ("StreamTitle='" + track_title.replace("'", '') + "';").encode('utf-8')
                            meta_length = math.ceil(len(meta_title) / 16)
                            meta_buffer = bytes((meta_length,)) + meta_title + (b'\x00' * ((meta_length * 16) - len(meta_title)))
                            new_meta = False
                            logging.debug('Metadata: ' + repr(meta_buffer))
                        else:
                            meta_buffer = b'\x00'
                        audio_interval = audio[:32768]
                        del audio[:32768]
                        try:
                            self.wfile.write(audio_interval)
                            self.wfile.write(meta_buffer)
                            if start_time != None and time.time() - start_time < 4:
                                time.sleep(4 - (time.time() - start_time))
                            start_time = time.time()
                        except (ConnectionResetError, ConnectionAbortedError) as e:
                            logging.info('Connection dropped: ' + str(e))
                            return
Пример #4
0
    def channel_stream(self, channel_number, rewind=0):
        channel_number = int(channel_number)
        rewind = int(rewind)

        if channel_number not in self.sbe.sxm.lineup:
            return self.file_not_found()

        channel = self.sbe.sxm.lineup[channel_number]
        url = 'http://{}:{}/'.format(self.sbe.config('hostname'),
                                     self.sbe.config('port'))

        logging.info('Streaming: Channel #{} "{}" with rewind {}'.format(
            channel_number, channel['name'], rewind))

        self.protocol_version = 'ICY'  # if we don't pretend to be shoutcast, doctors HATE us
        self.send_response_only(200)
        self.send_header('Content-type', 'audio/aacp')
        self.send_header('icy-br', '64')
        self.send_header('icy-name', channel['name'])
        self.send_header('icy-genre', channel['genre'])
        self.send_header('icy-url', url)
        self.send_header('icy-metaint', '32768')
        self.end_headers()

        channel_id = str(channel['channelKey'])
        track_title = ''
        start_time = None
        new_meta = False

        audio = bytearray()
        for ts_packet in self.sbe.sxm.packet_generator(channel_id, rewind):
            pes_streams = collections.defaultdict(bytearray)
            for pes_packet in mpegutils.parse_transport_stream(ts_packet):
                if 'payload' in pes_packet:
                    pes_streams[pes_packet['pid']].extend(
                        pes_packet['payload'])

            for pid, pes_stream in pes_streams.items():
                for es_packet in mpegutils.parse_packetized_elementary_stream(
                        pes_stream):
                    if pid == 768:
                        audio.extend(es_packet['payload'])
                    elif pid == 1024:
                        metadata = mpegutils.parse_sxm_metadata(
                            es_packet['payload'])
                        if metadata:
                            new_title = '{} - {}'.format(
                                metadata[1], metadata[0])
                            if new_title != track_title:
                                logging.info("Now playing: " + new_title)
                                track_title = new_title
                                new_meta = True

                    if len(audio) >= 32768:
                        if new_meta:
                            meta_title = ("StreamTitle='" +
                                          track_title.replace("'", '') +
                                          "';").encode('utf-8')
                            meta_length = math.ceil(len(meta_title) / 16)
                            meta_buffer = bytes(
                                (meta_length, )) + meta_title + (b'\x00' * (
                                    (meta_length * 16) - len(meta_title)))
                            new_meta = False
                            logging.debug('Metadata: ' + repr(meta_buffer))
                        else:
                            meta_buffer = b'\x00'
                        audio_interval = audio[:32768]
                        del audio[:32768]
                        try:
                            self.wfile.write(audio_interval)
                            self.wfile.write(meta_buffer)
                            if start_time != None and time.time(
                            ) - start_time < 4:
                                time.sleep(4 - (time.time() - start_time))
                            start_time = time.time()
                        except (ConnectionResetError,
                                ConnectionAbortedError) as e:
                            logging.info('Connection dropped: ' + str(e))
                            return