The files contained in this repository can be downloaded to your computer using a svn client.
On Linux you simply type the command displayed below.

This URL has Read-Only access.

Statistics
| Revision:

root / trunk / DomotiGa / CSqueezeServer.class @ 348

History | View | Annotate | Download (11.9 kB)

1
' Gambas class file
2
3
' Description:
4
' CSqueezeServer.class
5
' Provide basic support for Squeeze/SlimServer and Player control.
6
7
' Development Status:
8
' Just started developing this one, not complete yet.
9
10
' Links:
11
' http://www.logitechsqueezebox.com/
12
13
' DomotiGa - an open source home automation program.
14
' Copyright(C) 2008-2010 Ron Klinkien
15
16
' Read file called COPYING for license details.
17
18
PROPERTY TCPHost AS String
19
PROPERTY TCPPort AS String
20
PROPERTY SqueezeServerDebug AS Boolean
21
22
PRIVATE sTCPHost AS String
23
PRIVATE sTCPPort AS String
24
PRIVATE bSqueezeServerDebug AS Boolean
25
26
PUBLIC hSqueezeServer AS NEW Socket
27
PUBLIC tSqueezeServer AS Timer
28
29
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
30
' connect to the host:port
31
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32
PUBLIC FUNCTION Connect() AS Boolean
33
34
  ' try to close the connection
35
  TRY hSqueezeServer.Close
36
37
  ' get a new one
38
  hSqueezeServer = NEW Socket AS "SqueezeServer"
39
  hSqueezeServer.Connect(sTCPHost, sTCPPort)
40
41
  ' all ok
42
  RETURN TRUE
43
44
CATCH ' some errors
45
  Main.WriteLog(("Squeeze Server Error: ") & ERROR.Text)
46
  RETURN FALSE
47
48
END
49
50
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51
' connection is lost
52
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53
PUBLIC SUB SqueezeServer_Closed()
54
55
  Main.WriteLog(("Squeeze Server Error: TCP socket closed. (is server still running?)"))
56
57
END
58
59
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60
' connected to server
61
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
62
PUBLIC SUB SqueezeServer_Ready()
63
64
  DIM aPlayers, aPlayStr AS String[]
65
  DIM sPlayer AS String
66
67
  Main.WriteLog(("Squeeze Server TCP socket connected."))
68
  Main.WriteLog(("Squeeze Server is running version ") & GetVersion() & ".")
69
70
  aPlayers = GetPlayers()
71
  IF aPlayers.Count THEN
72
    Main.WriteLog(("Current player list:"))
73
    FOR EACH sPlayer IN aPlayers
74
      aPlayStr = Scan(sPlayer, "*^*^*")
75
      IF aPlayStr.Count = 3 THEN Main.WriteLog(("ID: ") & aPlayStr[0] & (" Name: ") & aPlayStr[1] & (" Connected: ") & IIf(aPlayStr[2] = "1", "Yes", "No") & (" Playing: ") & GetCurrentTitle(aPlayStr[0]))
76
    NEXT
77
  ELSE
78
    Main.WriteLog(("No players found."))
79
  END IF
80
  Main.WriteLog(("The Squeeze Server music database holds ") & GetAlbumCount() & (" albums and ") & GetSongCount() & (" songs from ") & GetArtistCount() & (" artists."))
81
82
  'SetVolume("00:00:00:00:00:01", 84)
83
  'PausePlayer("00:00:00:00:00:01")
84
  'PlayPlayer("00:00:00:00:00:01")
85
  'text = Search("Frank Zappa")
86
  'PRINT GetSongInfo("00:00:00:00:00:01", 1)
87
88
END
89
90
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
91
' send api command to server and return answer
92
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
93
PUBLIC SUB SendCommand(sCmd AS String, OPTIONAL sPlayerId AS String) AS String
94
95
  DIM iTries AS Integer = 5
96
  DIM sData AS String
97
98
  IF sPlayerId THEN sCmd = URLEncode(sPlayerId) & " " & sCmd
99
  IF bSqueezeServerDebug THEN Main.WriteDebugLog("[SqueezeServer] > " & sCmd)
100
  WRITE #hSqueezeServer, sCmd & Chr(10), Len(sCmd) + 1
101
102
  RETURN ReceiveData()
103
104
END
105
106
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
107
' send api command and params to server and return answer
108
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
109
PUBLIC SUB SendCommandParams(sCmd AS String, aParams AS String[], OPTIONAL sPlayerId AS String) AS String
110
111
  DIM sParam AS String
112
113
  FOR EACH sParam IN aParams
114
    sCmd &= " " & UrlEncode(sParam)
115
  NEXT
116
  IF sPlayerId THEN sCmd = URLEncode(sPlayerId) & " " & sCmd
117
  IF bSqueezeServerDebug THEN Main.WriteDebugLog("[SqueezeServer] > " & sCmd)
118
  WRITE #hSqueezeServer, sCmd & Chr(10), Len(sCmd) + 1
119
120
  RETURN ReceiveData()
121
122
END
123
124
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
125
' get the response
126
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127
PUBLIC SUB ReceiveData() AS String
128
129
  DIM iTries AS Integer = 30
130
  DIM sData AS String
131
132
  ' see if we got some data
133
  WHILE iTries > 0
134
    TRY LINE INPUT #hSqueezeServer, sData
135
    IF ERROR THEN
136
      ' not yet
137
      SLEEP 0.01
138
    ELSE
139
      ' got it
140
      BREAK
141
    END IF
142
    DEC iTries
143
  WEND
144
  IF bSqueezeServerDebug THEN Main.WriteDebugLog("[SqueezeServer] < " & URLDecode(sData))
145
146
  RETURN URLDecode(sData)
147
148
END
149
150
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
151
' count number of connected players
152
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153
PUBLIC SUB GetPlayerCount() AS Integer
154
155
  DIM sData AS String = SendCommand("player count ?")
156
157
  TRY RETURN Replace(sData, "player count ", "")
158
159
END
160
161
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
162
' gather squeezeserver playerid for each connected player
163
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164
PUBLIC SUB GetPlayers() AS String[]
165
166
  DIM aParams, aPlayers AS NEW String[]
167
  DIM sName, sId, sPlayers, sConn AS String
168
  DIM iLen, iPosName, iPos, iPosConn AS Integer
169
170
  aParams.Add("0")
171
  aParams.Add(GetPlayerCount())
172
  sPlayers = SendCommandParams("players", aParams)
173
  iPos = InStr(sPlayers, "playerid:")
174
175
  WHILE iPos > 0
176
    iLen = InStr(sPlayers, " ", iPos)
177
    sId = Mid(sPlayers, iPos + 9, iLen - iPos - 9)
178
    iPosName = InStr(sPlayers, "name:", iLen)
179
    IF iPosName THEN
180
      iLen = InStr(sPlayers, "model:", iPosName)
181
      sName = Mid(sPlayers, iPosName + 5, iLen - iPosName - 6)
182
    END IF
183
    iPosConn = InStr(sPlayers, "connected:", iLen)
184
    IF iPosConn THEN
185
      sConn = Mid(sPlayers, iPosConn + 10, 1)
186
    END IF
187
    aPlayers.Add(sId & "^" & sName & "^" & sConn)
188
    iPos = InStr(sPlayers, "playerid:", iPosConn)
189
  WEND
190
191
  RETURN aPlayers
192
193
END
194
195
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
196
' set volume of player with playerid
197
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
198
PRIVATE FUNCTION SetVolume(sPlayerId AS String, iVol AS Integer) AS String
199
200
  DIM aParams AS NEW String[]
201
202
  aParams.Add(iVol)
203
  IF iVol >= 0 OR IF iVol <= 100 THEN
204
    RETURN SendCommandParams("mixer volume", aParams, sPlayerId)
205
  END IF
206
207
END
208
209
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
210
' stop player with playerid
211
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212
PUBLIC FUNCTION StopPlayer(sPlayerId AS String) AS String
213
214
  RETURN SendCommand("stop", sPlayerId)
215
216
END FUNCTION
217
218
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
219
' pause player with playerid
220
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
221
PUBLIC FUNCTION PausePlayer(sPlayerId AS String) AS String
222
223
  RETURN SendCommand("pause", sPlayerId)
224
225
END
226
227
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
228
' play player with playerid
229
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
230
PUBLIC FUNCTION PlayPlayer(sPlayerId AS String) AS String
231
232
  RETURN SendCommand("play", sPlayerId)
233
234
END
235
236
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
237
' get songinfo from player with playerid and trackid
238
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239
PUBLIC FUNCTION GetSongInfo(sPlayerId AS String, iTrackId AS Integer) AS String
240
241
  DIM aParams AS NEW String[]
242
243
  aParams.Add("0")
244
  aParams.Add("100")
245
246
  RETURN SendCommandParams("songinfo", aParams, sPlayerId)
247
248
END
249
250
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251
' get current title from player with playerid
252
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
253
PUBLIC FUNCTION GetCurrentTitle(sPlayerId AS String) AS String
254
255
  DIM sData AS String = SendCommand("current_title ?", sPlayerId)
256
257
  TRY RETURN Replace(sData, "current_title ", "")
258
259
END
260
261
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
262
' show message on display of player with playerid
263
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
264
PUBLIC FUNCTION ShowMessage(sPlayerId AS String, sMessage AS String, iDuration AS Integer) AS String
265
266
  DIM aParams AS NEW String[]
267
268
  IF NOT Len(sMessage) THEN RETURN
269
270
  aParams.Add("line2:" & sMessage)
271
  aParams.Add("duration:" & iDuration)
272
  aParams.Add("centered:1")
273
  aParams.Add("font:huge")
274
275
  RETURN SendCommandParams("show", aParams, sPlayerId)
276
277
END
278
279
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
280
' search database for keywords
281
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
282
PUBLIC SUB Search(sFind AS String) AS String
283
284
  DIM aParams AS NEW String[]
285
286
  aParams.Add("0")
287
  aParams.Add("50")
288
  aParams.Add("term:" & sFind)
289
290
  RETURN SendCommandParams("search", aParams)
291
292
END
293
294
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
295
' get version of server
296
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
297
PUBLIC SUB GetVersion() AS String
298
299
  RETURN (Replace(SendCommand("version ?"), "version ", ""))
300
301
END
302
303
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
304
' get total albums found on server
305
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
306
PUBLIC SUB GetAlbumCount() AS String
307
308
  RETURN (Replace(SendCommand("info total albums ?"), "info total albums ", ""))
309
310
END
311
312
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
313
' get total songs found on server
314
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
315
PUBLIC SUB GetSongCount() AS String
316
317
  RETURN (Replace(SendCommand("info total songs ?"), "info total songs ", ""))
318
319
END
320
321
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
322
' get total artists found on server
323
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
324
PUBLIC SUB GetArtistCount() AS String
325
326
  RETURN (Replace(SendCommand("info total artists ?"), "info total artists ", ""))
327
328
END
329
330
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
331
' encode url
332
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
333
PRIVATE SUB URLEncode(URL AS String) AS String
334
335
  DIM iPos AS Integer
336
  DIM sRes, sCar AS String
337
338
  FOR iPos = 1 TO Len(URL)
339
    sCar = Mid$(URL, iPos, 1)
340
    IF sCar = " " THEN
341
      sCar = "%20"
342
    ELSE IF IsLetter(sCar) OR IF IsDigit(sCar) OR IF InStr("*-._", sCar) THEN
343
    ELSE
344
      sCar = "%" & Hex$(Asc(sCar), 2)
345
    ENDIF
346
    sRes &= sCar
347
  NEXT
348
349
  RETURN sRes
350
351
END
352
353
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
354
' decode url
355
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
356
PRIVATE FUNCTION URLDecode(sUrl AS String) AS String
357
358
  DIM sRes, sCar AS String
359
  DIM iPos AS Integer
360
361
  FOR iPos = 1 TO Len(sUrl)
362
    sCar = Mid$(sUrl, iPos, 1)
363
    IF sCar = "%20" THEN
364
      sCar = " "
365
    ELSE IF sCar = "%" THEN
366
      sCar = Chr$(Val("&H" & Mid$(sUrl, iPos + 1, 2)))
367
      iPos = iPos + 2
368
    ENDIF
369
    sRes = sRes & sCar
370
  NEXT
371
  sRes = Replace(sRes, "\r", "")
372
373
  RETURN sRes
374
375
END
376
377
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
378
' disconnect from the host
379
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
380
PUBLIC FUNCTION Disconnect() AS Boolean
381
382
  ' try to close the connection
383
  TRY hSqueezeServer.Close
384
  Main.WriteLog(("Squeeze Server TCP socket port close."))
385
386
  ' all ok
387
  RETURN TRUE
388
389
CATCH ' some errors
390
  Main.WriteLog(("Squeeze Server Error: ") & ERROR.Text)
391
  RETURN FALSE
392
393
END
394
395
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
396
' display error if connect failed
397
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
398
PUBLIC SUB SqueezeServer_Error()
399
400
  ' handle error
401
  SELECT CASE hSqueezeServer.Status
402
    CASE Net.CannotCreateSocket
403
      Main.WriteLog(("Squeeze Server: The system does not allow to create a socket."))
404
    CASE Net.HostNotFound
405
      Main.WriteLog(("Squeeze Server: Host '") & sTCPHost & ("' not found."))
406
    CASE Net.ConnectionRefused
407
      Main.WriteLog(("Squeeze Server: Unable to connect to SqueezeServer. Connection refused."))
408
    CASE Net.CannotRead
409
      Main.WriteLog(("Squeeze Server: Error reading data."))
410
    CASE Net.CannotWrite
411
      Main.WriteLog(("Squeeze Server: Error writing data."))
412
  END SELECT
413
414
END
415
416
' implement properties
417
PRIVATE FUNCTION TCPHost_Read() AS String
418
419
  RETURN sTCPHost
420
421
END
422
423
PRIVATE SUB TCPHost_Write(Value AS String)
424
425
  sTCPHost = Value
426
427
END
428
429
PRIVATE FUNCTION TCPPort_Read() AS String
430
431
  RETURN sTCPPort
432
433
END
434
435
PRIVATE FUNCTION TCPPort_Write(Value AS String)
436
437
  sTCPPort = Value
438
439
END
440
441
PRIVATE FUNCTION SqueezeServerDebug_Read() AS Boolean
442
443
  RETURN bSqueezeServerDebug
444
445
END
446
447
PRIVATE SUB SqueezeServerDebug_Write(Value AS Boolean)
448
449
  bSqueezeServerDebug = Value
450
451
END