File: mp3stream.py

package info (click to toggle)
mongrel2 1.12.0-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 5,976 kB
  • sloc: ansic: 39,083; python: 2,833; sql: 1,555; sh: 467; makefile: 360; asm: 189; yacc: 145; php: 73; awk: 28; sed: 5
file content (104 lines) | stat: -rw-r--r-- 2,618 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import time
import struct
from threading import Thread, Condition


class ConnectState(object):
    """
    Kind of a Queue but not.
    """

    def __init__(self):
        self.requests ={}
        self.wait_cond = Condition()

    def add(self, req):
        self.wait_cond.acquire()
        self.requests[req.conn_id] = req
        self.wait_cond.notify()
        self.wait_cond.release()


    def remove(self, req):
        self.wait_cond.acquire()
        try:
            del self.requests[req.conn_id]
        except:
            pass
        self.wait_cond.notify()
        self.wait_cond.release()

    def count(self):
        return len(self.requests)

    def available(self):
        self.wait_cond.acquire()
        self.wait_cond.wait()
        result = self.count()
        self.wait_cond.release()

        return result

    def connected(self):
        return self.requests.keys()



class Streamer(Thread):

    def __init__(self, mp3_files, state, conn, chunk_size, sender_id):
        super(Streamer, self).__init__()
        self.mp3_files = mp3_files
        self.state = state
        self.conn = conn
        self.chunk_size = chunk_size
        self.sender_id = sender_id


    def make_icy_info(self, data):
        icy_info_len = len(data)
        pad_len = (16 - (icy_info_len % 16)) % 16
        padding = struct.pack('B', 0) * pad_len
        return struct.pack('B', (icy_info_len + pad_len) / 16) + data + padding


    def stream_mp3(self, mp3_name):
        icy_info = self.make_icy_info("StreamTitle='%s';" % mp3_name)
        empty_md = self.make_icy_info("")

        print self.state.connected(), "Listeners connected."

        result = open(mp3_name, 'r')

        chunk = result.read(self.chunk_size)

        # the first one has our little header for the song
        self.conn.deliver(self.sender_id, self.state.connected(), chunk + icy_info)

        # all of them after that are empty
        while self.state.connected():
            chunk = result.read(self.chunk_size)

            if not chunk:
                break
            elif len(chunk) < self.chunk_size:
                chunk += empty_md * (self.chunk_size - len(chunk))

            self.conn.deliver(self.sender_id, self.state.connected(), chunk + empty_md)

            time.sleep(0.2)

        result.close()


    def run(self):
        print "RUNNING"
        while self.state.available():
            for mp3_name in self.mp3_files:
                print "Streaming %s" % mp3_name
                self.stream_mp3(mp3_name)
                if not self.state.connected():
                    break