1
+ import os
2
+ import logging
3
+ from overcast import Overcast
4
+ from pysimplesoap .server import SoapDispatcher , SOAPHandler
5
+ from BaseHTTPServer import HTTPServer
6
+
7
+ logging .basicConfig (level = logging .DEBUG )
8
+
9
+ log = logging .getLogger ('overcast-sonos' )
10
+
11
+ dispatcher = SoapDispatcher ('overcast-sonos' ,
12
+ location = 'http://localhost:8080/' ,
13
+ namespace = 'http://www.sonos.com/Services/1.1' ,
14
+ trace = True ,
15
+ debug = True
16
+ )
17
+
18
+ overcast = Overcast (os .environ ['OVERCAST_USERNAME' ], os .environ ['OVERCAST_PASSWORD' ])
19
+
20
+ mediaCollection = {'id' : str ,
21
+ 'title' : str ,
22
+ 'itemType' : str ,
23
+ 'artistId' : str ,
24
+ 'artist' : str ,
25
+ 'albumArtURI' : str ,
26
+ 'canPlay' : bool ,
27
+ 'canEnumerate' : bool ,
28
+ 'canAddToFavorites' : bool ,
29
+ 'canScroll' : bool ,
30
+ 'canSkip' : bool }
31
+
32
+ trackMetadata = {'artist' : str ,
33
+ 'albumArtist' : str ,
34
+ 'genreId' : str ,
35
+ 'duration' : int }
36
+
37
+ mediaMetadata = {'id' : str ,
38
+ 'title' : str ,
39
+ 'mimeType' : str ,
40
+ 'itemType' : str ,
41
+ 'trackMetadata' : trackMetadata }
42
+
43
+ ###
44
+
45
+ def getSessionId (username , password ):
46
+ log .debug ('at=getSessionId username=%s password=%s' , username , password )
47
+ return username
48
+
49
+ dispatcher .register_function (
50
+ 'getSessionId' , getSessionId ,
51
+ returns = {'getSessionIdResult' : str },
52
+ args = {'username' : str , 'password' : str }
53
+ )
54
+
55
+ ###
56
+
57
+ def getMetadata (id , index , count ):
58
+ log .debug ('at=getMetadata id=%s index=%s count=%s' , id , index , count )
59
+
60
+ if id == 'root' :
61
+ response = {'getMetadataResult' : [
62
+ {'index' : 0 , 'count' : 1 , 'total' : 1 },
63
+ {'mediaCollection' : {
64
+ 'id' : 'episodes' ,
65
+ 'title' : 'All Active Episodes' ,
66
+ 'itemType' : 'container' ,
67
+ 'canPlay' : False
68
+ }},
69
+ # {'mediaCollection': {
70
+ # 'id': 'podcasts',
71
+ # 'title': 'Podcasts',
72
+ # 'itemType': 'container',
73
+ # 'canPlay': False
74
+ # }},
75
+ ]}
76
+
77
+ elif id == 'episodes' :
78
+ episodes = overcast .get_active_episodes ()
79
+ response = {'getMetadataResult' : [{'index' : 0 , 'count' : len (episodes ), 'total' : len (episodes )}]}
80
+ for episode in episodes :
81
+ response ['getMetadataResult' ].append ({'mediaMetadata' : {
82
+ 'id' : 'episodes/' + episode ['id' ],
83
+ 'title' : episode ['title' ],
84
+ 'mimeType' : episode ['audio_type' ],
85
+ 'itemType' : 'track' ,
86
+ 'trackMetadata' : {
87
+ 'artist' : episode ['podcast_title' ],
88
+ 'albumArtist' : episode ['podcast_title' ],
89
+ 'genreId' : 'podcast' ,
90
+ 'duration' : episode ['duration' ],
91
+ }
92
+ }})
93
+
94
+ else :
95
+ logging .error ('unknown getMetadata id id=%s' , id )
96
+ response = {'getMetadataResult' : [{'index' : 0 , 'count' : 0 , 'total' : 0 }]}
97
+
98
+ log .debug ('at=getMetadata response=%s' , response )
99
+ return response
100
+
101
+ dispatcher .register_function (
102
+ 'getMetadata' , getMetadata ,
103
+ returns = {'getMetadataResult' : {'index' : int , 'count' : int , 'total' : int , 'mediaCollection' : mediaCollection }},
104
+ args = {'id' : str , 'index' : int , 'count' : int }
105
+ )
106
+
107
+ ###
108
+
109
+ def getMediaMetadata (id ):
110
+ log .debug ('at=getMediaMetadata id=%s' , id )
111
+ _ , episode_id = id .rsplit ('/' , 1 )
112
+ episode = overcast .get_episode_detail (episode_id )
113
+ response = {'getMediaMetadataResult' : {'mediaMetadata' : {
114
+ 'id' : id ,
115
+ 'title' : episode ['title' ],
116
+ 'mimeType' : episode ['audio_type' ],
117
+ 'itemType' : 'track' ,
118
+ 'trackMetadata' : {
119
+ 'artist' : episode ['podcast_title' ],
120
+ 'albumArtist' : episode ['podcast_title' ],
121
+ 'genreId' : 'podcast' ,
122
+ 'duration' : episode ['duration' ],
123
+ }
124
+ }}}
125
+ log .debug ('at=getMediaMetadata response=%s' , response )
126
+ return response
127
+
128
+ dispatcher .register_function (
129
+ 'getMediaMetadata' , getMediaMetadata ,
130
+ returns = {'getMediaMetadataResult' : mediaMetadata },
131
+ args = {'id' : str }
132
+ )
133
+
134
+ ###
135
+
136
+
137
+ def getMediaURI (id ):
138
+ log .debug ('at=getMediaURI id=%s' , id )
139
+ _ , episode_id = id .rsplit ('/' , 1 )
140
+ episode = overcast .get_episode_detail (episode_id )
141
+ response = {'getMediaURIResult' : episode ['audio_uri' ]}
142
+ log .debug ('at=getMediaMetadata response=%s' , response )
143
+ return response
144
+
145
+ dispatcher .register_function (
146
+ 'getMediaURI' , getMediaURI ,
147
+ returns = {'getMediaURIResult' : str },
148
+ args = {'id' : str }
149
+ )
150
+
151
+ ###
152
+
153
+ def getLastUpdate ():
154
+ log .debug ('at=getLastUpdate' )
155
+ return {'getLastUpdateResult' : {'catalog' : '0' , 'favorites' : '0' , 'pollInterval' : 60 }}
156
+
157
+ dispatcher .register_function (
158
+ 'getLastUpdate' , getLastUpdate ,
159
+ returns = {'getLastUpdateResult' : {'catalog' : str , 'favorites' : str , 'pollInterval' : int }},
160
+ args = None
161
+ )
162
+
163
+ if __name__ == '__main__' :
164
+ log .info ('at=start' )
165
+ httpd = HTTPServer (("" , 8080 ), SOAPHandler )
166
+ httpd .dispatcher = dispatcher
167
+ httpd .serve_forever ()
0 commit comments