Merge lp://qastaging/~thomsen/do-plugins/SqueezeCenter into lp://qastaging/do-plugins

Proposed by Thomsen
Status: Merged
Merged at revision: not available
Proposed branch: lp://qastaging/~thomsen/do-plugins/SqueezeCenter
Merge into: lp://qastaging/do-plugins
Diff against target: None lines
To merge this branch: bzr merge lp://qastaging/~thomsen/do-plugins/SqueezeCenter
Reviewer Review Type Date Requested Status
Alex Launi (community) Needs Information
Review via email: mp+9527@code.qastaging.launchpad.net
To post a comment you must log in.
Revision history for this message
Thomsen (thomsen) wrote :

New version with lots of fixes.

I haven't touched the makefile - who is responsible for updating these?

Revision history for this message
Alex Launi (alexlauni) wrote :

> New version with lots of fixes.
>
> I haven't touched the makefile - who is responsible for updating these?

You are; have you added/removed/renamed files? If not the makefile will still work.

Revision history for this message
Thomsen (thomsen) wrote :

Files have been added, yes. I'll look at it tomorrow.

2009/7/31 Alex Launi <email address hidden>

> > New version with lots of fixes.
> >
> > I haven't touched the makefile - who is responsible for updating these?
>
> You are; have you added/removed/renamed files? If not the makefile will
> still work.
> --
> https://code.launchpad.net/~thomsen/do-plugins/SqueezeCenter/+merge/9527<https://code.launchpad.net/%7Ethomsen/do-plugins/SqueezeCenter/+merge/9527>
> You are the owner of lp:~thomsen/do-plugins/SqueezeCenter.
>

--
Med venlig hilsen,
Anders Thomsen

Revision history for this message
Alex Launi (alexlauni) wrote :

the other thing is that you removed the addin.xml.in and replaced with
addin.xml- this is wrong. You need the addin.xml.in file.

--
--Alex Launi

Revision history for this message
Thomsen (thomsen) wrote :

I've tried fiddling with update_makefile.sh, automake.am and others and I
can't get it to work. Make just hangs...

Is there a guide to plugin development somewhere stating what files etc.
should contain? I couldn't find anything in the wiki.

2009/7/31 Alex Launi <email address hidden>

> the other thing is that you removed the addin.xml.in and replaced with
> addin.xml- this is wrong. You need the addin.xml.in file.
>
> --
> --Alex Launi
>
> https://code.launchpad.net/~thomsen/do-plugins/SqueezeCenter/+merge/9527<https://code.launchpad.net/%7Ethomsen/do-plugins/SqueezeCenter/+merge/9527>
> You are the owner of lp:~thomsen/do-plugins/SqueezeCenter.
>

--
Med venlig hilsen,
Anders Thomsen

Revision history for this message
Alex Launi (alexlauni) wrote :

You just edit the Makefile.am for Squeezecenter.

--
-- Alex Launi

655. By Anders Thomsen <email address hidden>

Hopeflully fixed makefile

Revision history for this message
Thomsen (thomsen) wrote :

Okay - I made changes to the make-file. Running make on my system just
hangs. Perhaps I need some dependencies for the other plugins or something.

Can you try to build it please?

Cheers,
Anders

2009/8/3 Alex Launi <email address hidden>

> You just edit the Makefile.am for Squeezecenter.
>
>
> --
> -- Alex Launi
>
> https://code.launchpad.net/~thomsen/do-plugins/SqueezeCenter/+merge/9527<https://code.launchpad.net/%7Ethomsen/do-plugins/SqueezeCenter/+merge/9527>
> You are the owner of lp:~thomsen/do-plugins/SqueezeCenter.
>

Revision history for this message
Alex Launi (alexlauni) wrote :

Your paths can't have spaces in their name.
% bzr mv Player\ commands PlayerCommands

and then fix the Makefile.am accordingly.

but it's still hanging, so I have no idea.

review: Abstain
Revision history for this message
Alex Launi (alexlauni) wrote :

Is this working yet?

review: Needs Information
Revision history for this message
Thomsen (thomsen) wrote :

> Is this working yet?

I haven't had the change of looking at it yet - been busy with other projects. It builds fine in MonoDevelop but running "make" just hangs... I'm not sure how to debug this...

656. By Anders Thomsen <email address hidden>

fixed build

657. By Anders Thomsen <email address hidden>

Removed debug-message

Revision history for this message
Thomsen (thomsen) wrote :

> Is this working yet?
Make fixed!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'SqueezeCenter/Resources/SqueezeCenter.addin.xml'
2--- SqueezeCenter/Resources/SqueezeCenter.addin.xml 1970-01-01 00:00:00 +0000
3+++ SqueezeCenter/Resources/SqueezeCenter.addin.xml 2009-07-31 19:40:23 +0000
4@@ -0,0 +1,40 @@
5+<Addin
6+ id="SqueezeCenter"
7+ namespace="Do"
8+ version="1.2.3"
9+ name="SqueezeCenter"
10+ description="Control Logitech Squeezebox and Transport audio players."
11+ author="Anders Thomsen"
12+ category="Community"
13+ defaultEnabled="false"
14+ >
15+
16+ <Runtime>
17+ <Import assembly="SqueezeCenter.dll"/>
18+ </Runtime>
19+
20+ <Localizer type="Gettext" catalog="gnome-do-plugins" location="@expanded_datadir@/locale" />
21+
22+ <Dependencies>
23+ <Addin id="Universe" version="1.0" />
24+ </Dependencies>
25+
26+ <!-- Extensions included in this assembly -->
27+ <Extension path="/Do/Action">
28+ <Action type="SqueezeCenter.Enqueue" />
29+ <Action type="SqueezeCenter.Play" />
30+ <Action type="SqueezeCenter.PlayerCommands.TurnOn" />
31+ <Action type="SqueezeCenter.PlayerCommands.TurnOff" />
32+ <Action type="SqueezeCenter.PlayerCommands.Pause" />
33+ <Action type="SqueezeCenter.PlayerCommands.Play" />
34+ <Action type="SqueezeCenter.PlayerCommands.Sync" />
35+ <Action type="SqueezeCenter.PlayerCommands.Unsync" />
36+ <Action type="SqueezeCenter.PlayerCommands.Prev" />
37+ <Action type="SqueezeCenter.PlayerCommands.Next" />
38+ </Extension>
39+
40+ <Extension path="/Do/ItemSource">
41+ <ItemSource type="SqueezeCenter.ItemSource" />
42+ </Extension>
43+
44+</Addin>
45
46=== removed file 'SqueezeCenter/Resources/SqueezeCenter.addin.xml.in'
47--- SqueezeCenter/Resources/SqueezeCenter.addin.xml.in 2009-06-22 21:50:13 +0000
48+++ SqueezeCenter/Resources/SqueezeCenter.addin.xml.in 1970-01-01 00:00:00 +0000
49@@ -1,39 +0,0 @@
50-<Addin
51- id="SqueezeCenter"
52- namespace="Do"
53- version="1.1"
54- name="SqueezeCenter"
55- description="Control Logitech Squeezebox and Transport audio players."
56- author="Anders Thomsen"
57- category="Community"
58- defaultEnabled="false"
59- >
60-
61- <Runtime>
62- <Import assembly="SqueezeCenter.dll"/>
63- </Runtime>
64-
65- <Localizer type="Gettext" catalog="gnome-do-plugins" location="@expanded_datadir@/locale" />
66-
67- <Dependencies>
68- <Addin id="Universe" version="1.0" />
69- </Dependencies>
70-
71- <!-- Extensions included in this assembly -->
72- <Extension path="/Do/Action">
73- <Action type="SqueezeCenter.Enqueue" />
74- <Action type="SqueezeCenter.Play" />
75- <Action type="SqueezeCenter.TurnOn" />
76- <Action type="SqueezeCenter.TurnOff" />
77- <Action type="SqueezeCenter.Pause" />
78- <Action type="SqueezeCenter.Sync" />
79- <Action type="SqueezeCenter.Unsync" />
80- <Action type="SqueezeCenter.Prev" />
81- <Action type="SqueezeCenter.Next" />
82- </Extension>
83-
84- <Extension path="/Do/ItemSource">
85- <ItemSource type="SqueezeCenter.ItemSource" />
86- </Extension>
87-
88-</Addin>
89
90=== modified file 'SqueezeCenter/SqueezeCenterPlugin.mdp'
91--- SqueezeCenter/SqueezeCenterPlugin.mdp 2009-06-23 00:52:54 +0000
92+++ SqueezeCenter/SqueezeCenterPlugin.mdp 2009-07-31 19:40:23 +0000
93@@ -27,21 +27,31 @@
94 <File name="src/NetworkStreamTextReader.cs" subtype="Code" buildaction="Compile" />
95 <File name="src/PlayCommand.cs" subtype="Code" buildaction="Compile" />
96 <File name="src/Player.cs" subtype="Code" buildaction="Compile" />
97- <File name="src/PlayerCommands.cs" subtype="Code" buildaction="Compile" />
98 <File name="src/RadioItem.cs" subtype="Code" buildaction="Compile" />
99 <File name="src/Server.cs" subtype="Code" buildaction="Compile" />
100 <File name="src/Settings.cs" subtype="Code" buildaction="Compile" />
101 <File name="src/Util.cs" subtype="Code" buildaction="Compile" />
102+ <File name="src/SqueezeCenterItem.cs" subtype="Code" buildaction="Compile" />
103+ <File name="src/Player commands" subtype="Directory" buildaction="Compile" />
104+ <File name="src/Player commands/PlayerCommand.cs" subtype="Code" buildaction="Compile" />
105+ <File name="src/Player commands/TurnOn.cs" subtype="Code" buildaction="Compile" />
106+ <File name="src/Player commands/TurnOff.cs" subtype="Code" buildaction="Compile" />
107+ <File name="src/Player commands/Pause.cs" subtype="Code" buildaction="Compile" />
108+ <File name="src/Player commands/Sync.cs" subtype="Code" buildaction="Compile" />
109+ <File name="src/Player commands/Unsync.cs" subtype="Code" buildaction="Compile" />
110+ <File name="src/Player commands/Prev.cs" subtype="Code" buildaction="Compile" />
111+ <File name="src/Player commands/Next.cs" subtype="Code" buildaction="Compile" />
112+ <File name="src/Player commands/Play.cs" subtype="Code" buildaction="Compile" />
113 <File name="Resources/SqueezeCenter.addin.xml" subtype="Code" buildaction="EmbedAsResource" />
114 <File name="Resources/icons/artist.svg" subtype="Code" buildaction="EmbedAsResource" />
115 <File name="Resources/icons/radio.png" subtype="Code" buildaction="EmbedAsResource" />
116- <File name="Resources/icons/radio.xcf" subtype="Code" buildaction="EmbedAsResource" />
117- <File name="Resources/icons/squeezebox.xcf" subtype="Code" buildaction="EmbedAsResource" />
118+ <File name="Resources/icons/radio.xcf" subtype="Code" buildaction="Nothing" />
119+ <File name="Resources/icons/squeezebox.xcf" subtype="Code" buildaction="Nothing" />
120 <File name="Resources/icons/sync.png" subtype="Code" buildaction="EmbedAsResource" />
121 <File name="Resources/icons/unsync.png" subtype="Code" buildaction="EmbedAsResource" />
122- <File name="Resources/icons/unsync.xcf" subtype="Code" buildaction="EmbedAsResource" />
123- <File name="Resources/icons/SB_off.png" subtype="Code" buildaction="Nothing" />
124- <File name="Resources/icons/SB_on.png" subtype="Code" buildaction="Nothing" />
125+ <File name="Resources/icons/unsync.xcf" subtype="Code" buildaction="Nothing" />
126+ <File name="Resources/icons/SB_off.png" subtype="Code" buildaction="EmbedAsResource" />
127+ <File name="Resources/icons/SB_on.png" subtype="Code" buildaction="EmbedAsResource" />
128 <File name="Resources/icons/sync_sb.xcf" subtype="Code" buildaction="Nothing" />
129 </Contents>
130 <References>
131
132=== modified file 'SqueezeCenter/src/EnqueueCommand.cs'
133--- SqueezeCenter/src/EnqueueCommand.cs 2008-12-24 04:37:17 +0000
134+++ SqueezeCenter/src/EnqueueCommand.cs 2009-07-31 19:40:23 +0000
135@@ -41,25 +41,17 @@
136
137 public override IEnumerable<Type> SupportedItemTypes {
138 get {
139- return new Type[] {
140- typeof (MusicItem),
141- };
142+ yield return typeof (MusicItem);
143 }
144 }
145
146 public override bool ModifierItemsOptional
147 {
148 get {
149- return Server.Instance.GetConnectedPlayers ().Count == 0;
150+ return !Player.GetAllConnectedPlayers().Any ();
151 }
152 }
153
154- public override IEnumerable<Item> DynamicModifierItemsForItem(Item item)
155- {
156- // this converts converts the list of players to an array of Item
157- return Server.Instance.GetConnectedPlayersAsItem ().ToArray ();
158- }
159-
160 public override bool SupportsModifierItemForItems (IEnumerable<Item> items, Item modifier)
161 {
162 return true;
163@@ -68,27 +60,25 @@
164 public override IEnumerable<Type> SupportedModifierItemTypes
165 {
166 get {
167- return new Type[] {
168- typeof (Player),
169- };
170+ yield return typeof (Player);
171 }
172 }
173
174 public override bool SupportsItem (Item item)
175 {
176- return (item is MusicItem);
177+ return item is MusicItem && ((MusicItem)item).Available;
178 }
179
180 public override IEnumerable<Item> Perform (IEnumerable<Item> items, IEnumerable<Item> modItems)
181 {
182- Player player;
183-
184+ SqueezeCenter.Player player;
185+
186 if (modItems.Any ()) {
187 player = modItems.First () as Player;
188 }
189 else {
190- List<Player> availablePlayers = Server.Instance.GetConnectedPlayers ();
191- if (availablePlayers.Count > 0) {
192+ Player[] availablePlayers = Player.GetAllConnectedPlayers ();
193+ if (availablePlayers.Length > 0) {
194 player = availablePlayers[0];
195 }
196 else {
197@@ -96,7 +86,7 @@
198 }
199 }
200
201- Server.Instance.AddItemsToPlayer (player, Util.Cast<Item, MusicItem>(items));
202+ Server.Instance.AddItemsToPlayer (player, items.Cast<MusicItem>());
203 return null;
204 }
205 }
206
207=== modified file 'SqueezeCenter/src/ItemSource.cs'
208--- SqueezeCenter/src/ItemSource.cs 2009-01-15 06:17:08 +0000
209+++ SqueezeCenter/src/ItemSource.cs 2009-07-31 19:40:23 +0000
210@@ -15,7 +15,7 @@
211 using System.IO;
212 using System.Collections.Generic;
213 using System.Threading;
214-
215+using System.Linq;
216
217 using Do.Universe;
218 using Do.Platform.Linux;
219@@ -48,12 +48,10 @@
220
221 public override IEnumerable<Type> SupportedItemTypes {
222 get {
223- return new Type[] {
224- typeof (MusicItem),
225- typeof (RadioItem),
226- typeof (BrowseMusicItem),
227- typeof (IApplicationItem),
228- };
229+ yield return typeof (MusicItem);
230+ yield return typeof (RadioItem);
231+ yield return typeof (BrowseMusicItem);
232+ yield return typeof (IApplicationItem);
233 }
234 }
235
236@@ -115,7 +113,8 @@
237 }
238
239 // Add players
240- items.AddRange (Server.Instance.GetConnectedPlayersAsItem ());
241+ items.AddRange (Player.GetAllConnectedPlayers ().Cast<Item> ());
242+
243
244 // Add browse features
245 items.Add (new BrowseAlbumsMusicItem ());
246@@ -127,5 +126,6 @@
247 foreach (Item album in albums) items.Add (album);
248 foreach (Item artist in artists) items.Add (artist);
249 }
250+
251 }
252 }
253
254=== modified file 'SqueezeCenter/src/MusicItem.cs'
255--- SqueezeCenter/src/MusicItem.cs 2008-12-24 04:37:17 +0000
256+++ SqueezeCenter/src/MusicItem.cs 2009-07-31 19:40:23 +0000
257@@ -19,21 +19,25 @@
258
259 namespace SqueezeCenter
260 {
261- public abstract class MusicItem : Item
262+
263+ public abstract class MusicItem : SqueezeCenterItem
264 {
265+
266 public readonly int Id;
267
268 public MusicItem (int id)
269 {
270- this.Id = id;
271+ this.Id = id;
272 }
273
274 public abstract string SqueezeCenterIdKey { get; }
275-
276+ public override abstract string Name { get; }
277+ public override abstract string Description { get; }
278+ public override abstract string Icon { get; }
279 }
280
281 public class AlbumMusicItem : MusicItem
282- {
283+ {
284 public readonly string Album, Year;
285 readonly ArtistMusicItem artist;
286 readonly int firstSongId;
287
288=== modified file 'SqueezeCenter/src/NetworkStreamTextReader.cs'
289--- SqueezeCenter/src/NetworkStreamTextReader.cs 2008-12-24 04:37:17 +0000
290+++ SqueezeCenter/src/NetworkStreamTextReader.cs 2009-07-31 19:40:23 +0000
291@@ -55,7 +55,7 @@
292
293 if (this.disconnected)
294 {
295- //throw new System.IO.IOException ("Connection closed");
296+ throw new System.IO.IOException ("Connection closed");
297 }
298
299 // return first line of data or null if no data is available
300
301=== modified file 'SqueezeCenter/src/PlayCommand.cs'
302--- SqueezeCenter/src/PlayCommand.cs 2008-12-24 04:37:17 +0000
303+++ SqueezeCenter/src/PlayCommand.cs 2009-07-31 19:40:23 +0000
304@@ -45,10 +45,8 @@
305
306 public override IEnumerable<Type> SupportedItemTypes {
307 get {
308- return new Type[] {
309- typeof (MusicItem),
310- typeof (RadioSubItem)
311- };
312+ yield return typeof (MusicItem);
313+ yield return typeof (RadioSubItem);
314 }
315 }
316
317@@ -56,17 +54,10 @@
318 public override bool ModifierItemsOptional
319 {
320 get {
321- return Server.Instance.GetConnectedPlayers ().Count == 0;
322+ return !Player.GetAllConnectedPlayers ().Any ();
323 }
324 }
325-
326- public override IEnumerable<Item> DynamicModifierItemsForItem(Item item)
327- {
328- // this converts converts the list of players to an array of Item
329- IEnumerable<Item> result = Server.Instance.GetConnectedPlayersAsItem ().ToArray ();
330- return result;
331- }
332-
333+
334 public override bool SupportsModifierItemForItems (IEnumerable<Item> items, Item modifier)
335 {
336 return true;
337@@ -75,15 +66,13 @@
338 public override IEnumerable<Type> SupportedModifierItemTypes
339 {
340 get {
341- return new Type[] {
342- typeof (Player),
343- };
344+ yield return typeof (Player);
345 }
346 }
347
348 public override bool SupportsItem (Item item)
349 {
350- return (item is MusicItem) || (item is RadioSubItem /*&& !(item as RadioSubItem).HasItems*/);
351+ return (item is MusicItem || item is RadioSubItem) && (item is SqueezeCenterItem && ((SqueezeCenterItem)item).Available);
352 }
353
354 public override IEnumerable<Item> Perform (IEnumerable<Item> items, IEnumerable<Item> modItems)
355@@ -95,7 +84,7 @@
356 }
357
358 else {
359- List<Player> availablePlayers = Server.Instance.GetConnectedPlayers ();
360+ IList<Player> availablePlayers = Player.GetAllConnectedPlayers ();
361 if (availablePlayers.Count > 0) {
362 player = availablePlayers[0];
363 }
364@@ -105,7 +94,7 @@
365 }
366
367 if (items.First () is MusicItem) {
368- Server.Instance.LoadItemsToPlayer (player, Util.Cast<Item, MusicItem> (items));
369+ Server.Instance.LoadItemsToPlayer (player, items.OfType<MusicItem> ());
370 }
371 else if (items.First () is RadioSubItem) {
372 Server.Instance.ExecuteCommand (string.Format ("{0} {1} playlist play item_id:{2}",
373
374=== added directory 'SqueezeCenter/src/Player commands'
375=== added file 'SqueezeCenter/src/Player commands/Next.cs'
376--- SqueezeCenter/src/Player commands/Next.cs 1970-01-01 00:00:00 +0000
377+++ SqueezeCenter/src/Player commands/Next.cs 2009-07-31 19:40:23 +0000
378@@ -0,0 +1,36 @@
379+// Next.cs created with MonoDevelop
380+// User: anders at 18:15 18-01-2009
381+//
382+//// This program is free software: you can redistribute it and/or modify
383+//// it under the terms of the GNU General Public License as published by
384+//// the Free Software Foundation, either version 3 of the License, or
385+//// (at your option) any later version.
386+////
387+//// This program is distributed in the hope that it will be useful,
388+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
389+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
390+//// GNU General Public License for more details.
391+////
392+//// You should have received a copy of the GNU General Public License
393+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
394+
395+using System;
396+using Do.Universe;
397+
398+namespace SqueezeCenter.PlayerCommands
399+{
400+
401+ public class Next : PlayerCommand
402+ {
403+ public Next () : base(
404+ "Next", "Next track", "gtk-media-next-ltr",
405+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped}
406+ ) {}
407+
408+ public override string GetCommand (Player player, Item modifierItem)
409+ {
410+ return string.Format ("{0} playlist index +1", player.Id);
411+ }
412+
413+ }
414+}
415
416=== added file 'SqueezeCenter/src/Player commands/Pause.cs'
417--- SqueezeCenter/src/Player commands/Pause.cs 1970-01-01 00:00:00 +0000
418+++ SqueezeCenter/src/Player commands/Pause.cs 2009-07-31 19:40:23 +0000
419@@ -0,0 +1,36 @@
420+// Pause.cs created with MonoDevelop
421+// User: anders at 15:11 18-01-2009
422+//
423+//// This program is free software: you can redistribute it and/or modify
424+//// it under the terms of the GNU General Public License as published by
425+//// the Free Software Foundation, either version 3 of the License, or
426+//// (at your option) any later version.
427+////
428+//// This program is distributed in the hope that it will be useful,
429+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
430+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
431+//// GNU General Public License for more details.
432+////
433+//// You should have received a copy of the GNU General Public License
434+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
435+
436+using System;
437+using Do.Universe;
438+
439+namespace SqueezeCenter.PlayerCommands
440+{
441+
442+ public class Pause : PlayerCommand
443+ {
444+ public Pause () : base (
445+ "Pause", "Toggle pause on the player", "gtk-media-pause",
446+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped}
447+ ) {}
448+
449+ public override string GetCommand (Player player, Item modifierItem)
450+ {
451+ return string.Format ("{0} pause", player.Id);
452+ }
453+
454+ }
455+}
456
457=== added file 'SqueezeCenter/src/Player commands/Play.cs'
458--- SqueezeCenter/src/Player commands/Play.cs 1970-01-01 00:00:00 +0000
459+++ SqueezeCenter/src/Player commands/Play.cs 2009-07-31 19:40:23 +0000
460@@ -0,0 +1,36 @@
461+// Play.cs created with MonoDevelop
462+// User: anders at 21:27 18-01-2009
463+//
464+//// This program is free software: you can redistribute it and/or modify
465+//// it under the terms of the GNU General Public License as published by
466+//// the Free Software Foundation, either version 3 of the License, or
467+//// (at your option) any later version.
468+////
469+//// This program is distributed in the hope that it will be useful,
470+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
471+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
472+//// GNU General Public License for more details.
473+////
474+//// You should have received a copy of the GNU General Public License
475+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
476+
477+using System;
478+using Do.Universe;
479+
480+namespace SqueezeCenter.PlayerCommands
481+{
482+
483+ public class Play : PlayerCommand
484+ {
485+ public Play () : base (
486+ "Play", "Play", "gtk-media-play-ltr",
487+ new PlayerStatus[] {PlayerStatus.Paused, PlayerStatus.Stopped, PlayerStatus.TurnedOff}
488+ ) {}
489+
490+ public override string GetCommand (Player player, Item modifierItem)
491+ {
492+ return string.Format ("{0} play", player.Id);
493+ }
494+
495+ }
496+}
497
498=== added file 'SqueezeCenter/src/Player commands/PlayerCommand.cs'
499--- SqueezeCenter/src/Player commands/PlayerCommand.cs 1970-01-01 00:00:00 +0000
500+++ SqueezeCenter/src/Player commands/PlayerCommand.cs 2009-07-31 19:40:23 +0000
501@@ -0,0 +1,71 @@
502+// This program is free software: you can redistribute it and/or modify
503+// it under the terms of the GNU General Public License as published by
504+// the Free Software Foundation, either version 3 of the License, or
505+// (at your option) any later version.
506+//
507+// This program is distributed in the hope that it will be useful,
508+// but WITHOUT ANY WARRANTY; without even the implied warranty of
509+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
510+// GNU General Public License for more details.
511+//
512+// You should have received a copy of the GNU General Public License
513+// along with this program. If not, see <http://www.gnu.org/licenses/>.
514+
515+using System;
516+using System.Linq;
517+using Do.Universe;
518+using System.Collections.Generic;
519+
520+namespace SqueezeCenter.PlayerCommands
521+{
522+
523+ public abstract class PlayerCommand : Act
524+ {
525+ string name;
526+ string description;
527+ string icon;
528+ IEnumerable<PlayerStatus> requiredPlayerStatus;
529+
530+ public PlayerCommand(string name, string description, string icon, IEnumerable<PlayerStatus> requiredPlayerStatus)
531+ {
532+ this.name = name;
533+ this.description = description;
534+ this.icon = icon;
535+ this.requiredPlayerStatus = requiredPlayerStatus;
536+ }
537+
538+ public override string Name {
539+ get { return name; }
540+ }
541+
542+ public override string Description {
543+ get { return description; }
544+ }
545+
546+ public override string Icon {
547+ get { return icon; }
548+ }
549+
550+ public override IEnumerable<Type> SupportedItemTypes {
551+ get {
552+ yield return typeof (Player);
553+ }
554+ }
555+
556+ public override bool SupportsItem (Item item)
557+ {
558+ Player player = (Player) item;
559+ return player.Available && this.requiredPlayerStatus.Contains (player.Status);
560+ }
561+
562+ public abstract string GetCommand (Player player, Item modifierItem);
563+
564+ public override IEnumerable<Item> Perform (IEnumerable<Item> items, IEnumerable<Item> modifierItems)
565+ {
566+ string command = GetCommand (items.First () as Player, modifierItems.FirstOrDefault ());
567+ Server.Instance.ExecuteCommand (command);
568+
569+ return null;
570+ }
571+ }
572+}
573
574=== added file 'SqueezeCenter/src/Player commands/Prev.cs'
575--- SqueezeCenter/src/Player commands/Prev.cs 1970-01-01 00:00:00 +0000
576+++ SqueezeCenter/src/Player commands/Prev.cs 2009-07-31 19:40:23 +0000
577@@ -0,0 +1,36 @@
578+// Prev.cs created with MonoDevelop
579+// User: anders at 18:14 18-01-2009
580+//
581+//// This program is free software: you can redistribute it and/or modify
582+//// it under the terms of the GNU General Public License as published by
583+//// the Free Software Foundation, either version 3 of the License, or
584+//// (at your option) any later version.
585+////
586+//// This program is distributed in the hope that it will be useful,
587+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
588+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
589+//// GNU General Public License for more details.
590+////
591+//// You should have received a copy of the GNU General Public License
592+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
593+
594+using System;
595+using Do.Universe;
596+
597+namespace SqueezeCenter.PlayerCommands
598+{
599+
600+ public class Prev : PlayerCommand
601+ {
602+ public Prev () : base(
603+ "Previous", "Previous track", "gtk-media-previous-ltr",
604+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped}
605+ ) {}
606+
607+ public override string GetCommand (Player player, Item modifierItem)
608+ {
609+ return string.Format ("{0} playlist index -1", player.Id);
610+ }
611+
612+ }
613+}
614
615=== added file 'SqueezeCenter/src/Player commands/Sync.cs'
616--- SqueezeCenter/src/Player commands/Sync.cs 1970-01-01 00:00:00 +0000
617+++ SqueezeCenter/src/Player commands/Sync.cs 2009-07-31 19:40:23 +0000
618@@ -0,0 +1,57 @@
619+// Sync.cs created with MonoDevelop
620+// User: anders at 15:12 18-01-2009
621+//
622+//// This program is free software: you can redistribute it and/or modify
623+//// it under the terms of the GNU General Public License as published by
624+//// the Free Software Foundation, either version 3 of the License, or
625+//// (at your option) any later version.
626+////
627+//// This program is distributed in the hope that it will be useful,
628+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
629+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
630+//// GNU General Public License for more details.
631+////
632+//// You should have received a copy of the GNU General Public License
633+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
634+
635+using System;
636+using System.Collections.Generic;
637+using System.Linq;
638+using Do.Universe;
639+
640+namespace SqueezeCenter.PlayerCommands
641+{
642+
643+ public class Sync : PlayerCommand
644+ {
645+ public Sync () : base(
646+ "Sync with", "Synchronize this player with another",
647+ "sync.png@" + typeof (Sync).Assembly.FullName,
648+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped, PlayerStatus.TurnedOff}
649+ ) {}
650+
651+ public override IEnumerable<Type> SupportedModifierItemTypes {
652+ get {
653+ yield return typeof (Player);
654+ }
655+ }
656+
657+ public override bool SupportsModifierItemForItems (IEnumerable<Item> items, Item modItem)
658+ {
659+ // all players except the current one
660+ return !items.Contains (modItem);
661+ }
662+
663+ public override bool ModifierItemsOptional
664+ {
665+ get {
666+ return false;
667+ }
668+ }
669+
670+ public override string GetCommand (Player player, Item modifierItem)
671+ {
672+ return string.Format ("{1} sync {0}", player.Id, (modifierItem as Player).Id);
673+ }
674+ }
675+}
676
677=== added file 'SqueezeCenter/src/Player commands/TurnOff.cs'
678--- SqueezeCenter/src/Player commands/TurnOff.cs 1970-01-01 00:00:00 +0000
679+++ SqueezeCenter/src/Player commands/TurnOff.cs 2009-07-31 19:40:23 +0000
680@@ -0,0 +1,35 @@
681+// TurnOff.cs created with MonoDevelop
682+// User: anders at 15:10 18-01-2009
683+//
684+//// This program is free software: you can redistribute it and/or modify
685+//// it under the terms of the GNU General Public License as published by
686+//// the Free Software Foundation, either version 3 of the License, or
687+//// (at your option) any later version.
688+////
689+//// This program is distributed in the hope that it will be useful,
690+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
691+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
692+//// GNU General Public License for more details.
693+////
694+//// You should have received a copy of the GNU General Public License
695+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
696+
697+using System;
698+using Do.Universe;
699+
700+namespace SqueezeCenter.PlayerCommands
701+{
702+
703+ public class TurnOff : PlayerCommand
704+ {
705+ public TurnOff () : base("Turn off", "Turn off the player", "gnome-shutdown",
706+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped}
707+ ) {}
708+
709+ public override string GetCommand (Player player, Item modifierItem)
710+ {
711+ return string.Format ("{0} power 0", player.Id);
712+ }
713+
714+ }
715+}
716
717=== added file 'SqueezeCenter/src/Player commands/TurnOn.cs'
718--- SqueezeCenter/src/Player commands/TurnOn.cs 1970-01-01 00:00:00 +0000
719+++ SqueezeCenter/src/Player commands/TurnOn.cs 2009-07-31 19:40:23 +0000
720@@ -0,0 +1,34 @@
721+// TurnOn.cs created with MonoDevelop
722+// User: anders at 15:08 18-01-2009
723+//
724+//// This program is free software: you can redistribute it and/or modify
725+//// it under the terms of the GNU General Public License as published by
726+//// the Free Software Foundation, either version 3 of the License, or
727+//// (at your option) any later version.
728+////
729+//// This program is distributed in the hope that it will be useful,
730+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
731+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
732+//// GNU General Public License for more details.
733+////
734+//// You should have received a copy of the GNU General Public License
735+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
736+
737+using System;
738+using Do.Universe;
739+
740+namespace SqueezeCenter.PlayerCommands
741+{
742+
743+ public class TurnOn : PlayerCommand
744+ {
745+ public TurnOn () : base(
746+ "Turn on", "Turn on the player", "sunny",
747+ new PlayerStatus[] {PlayerStatus.TurnedOff}) {}
748+
749+ public override string GetCommand (Player player, Item modifierItem)
750+ {
751+ return string.Format ("{0} power 1", player.Id);
752+ }
753+ }
754+}
755
756=== added file 'SqueezeCenter/src/Player commands/Unsync.cs'
757--- SqueezeCenter/src/Player commands/Unsync.cs 1970-01-01 00:00:00 +0000
758+++ SqueezeCenter/src/Player commands/Unsync.cs 2009-07-31 19:40:23 +0000
759@@ -0,0 +1,55 @@
760+// Unsync.cs created with MonoDevelop
761+// User: anders at 15:14 18-01-2009
762+//
763+//// This program is free software: you can redistribute it and/or modify
764+//// it under the terms of the GNU General Public License as published by
765+//// the Free Software Foundation, either version 3 of the License, or
766+//// (at your option) any later version.
767+////
768+//// This program is distributed in the hope that it will be useful,
769+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
770+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
771+//// GNU General Public License for more details.
772+////
773+//// You should have received a copy of the GNU General Public License
774+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
775+
776+using System;
777+using System.Collections.Generic;
778+using Do.Universe;
779+
780+namespace SqueezeCenter.PlayerCommands
781+{
782+
783+ public class Unsync : PlayerCommand
784+ {
785+ public Unsync () : base(
786+ "Unsync", "Stop synchronizing this player with another",
787+ "unsync.png@" + typeof (Unsync).Assembly.FullName,
788+ new PlayerStatus[] {PlayerStatus.Playing, PlayerStatus.Paused, PlayerStatus.Stopped, PlayerStatus.TurnedOff}
789+ ) {}
790+
791+ public override string GetCommand (Player player, Item modifierItem)
792+ {
793+ return string.Format ("{0} sync -", player.Id);
794+ }
795+
796+ public override bool SupportsModifierItemForItems (IEnumerable<Item> items, Item modItem)
797+ {
798+ return false;
799+ }
800+
801+ public override bool SupportsItem (Item item)
802+ {
803+ return base.SupportsItem (item) && (item as Player).IsSynced;
804+ }
805+
806+
807+ public override bool ModifierItemsOptional
808+ {
809+ get {
810+ return true;
811+ }
812+ }
813+ }
814+}
815
816=== modified file 'SqueezeCenter/src/Player.cs'
817--- SqueezeCenter/src/Player.cs 2009-01-15 06:17:08 +0000
818+++ SqueezeCenter/src/Player.cs 2009-07-31 19:40:23 +0000
819@@ -16,28 +16,81 @@
820 using System.Collections.Generic;
821 using System.IO;
822 using System.Reflection;
823+using System.Linq;
824 using Do.Universe;
825
826 namespace SqueezeCenter
827 {
828
829- public class Player : Item
830+ public class Player : SqueezeCenterItem
831 {
832+ static Dictionary<string, Player> players = new Dictionary<string, Player> ();
833+
834+ public static void CreatePlayer (string id, string name, string model, bool connected, bool poweredOn, bool canPowerOff)
835+ {
836+ // check if player was created before
837+ lock (Player.players)
838+ {
839+ Player p;
840+ if (!Player.players.TryGetValue (id, out p))
841+ {
842+#if VERBOSE_OUTPUT
843+ Console.WriteLine("SQC: New player " + name);
844+#endif
845+ p = new Player(id);
846+ Player.players.Add (id, p);
847+ }
848+ p.name = name;
849+ p.model = model;
850+ p.canPowerOff = canPowerOff;
851+
852+ if (!connected)
853+ p.Status = PlayerStatus.Disconnected;
854+ else {
855+ if (!poweredOn)
856+ p.Status = PlayerStatus.TurnedOff;
857+ else
858+ p.Status = PlayerStatus.Stopped; // this we don't know, but it'll be updated later.
859+ }
860+ p.syncedWith.Clear();
861+ p.Available = true;
862+#if VERBOSE_OUTPUT
863+ Console.WriteLine("SQC: Existing player " + name);
864+#endif
865+ }
866+ }
867+
868+ public static Player GetFromId(string id)
869+ {
870+ Player p;
871+ lock (Player.players)
872+ if (!Player.players.TryGetValue(id, out p))
873+ p = null;
874+ return p;
875+ }
876+
877+ public static Player[] GetAllPlayers()
878+ {
879+ lock (Player.players)
880+ return Player.players.Values.Where (p => p.Available).ToArray ();
881+ }
882+
883+ public static Player[] GetAllConnectedPlayers()
884+ {
885+ lock (Player.players)
886+ return Player.players.Values.Where (p => p.Available && p.Status != PlayerStatus.Disconnected).ToArray();
887+ }
888+
889 string id, name, model;
890- bool connected, poweredOn, canPowerOff;
891+ bool canPowerOff;
892 List<Player> syncedWith;
893 string syncedWithStr;
894+ PlayerStatus status;
895
896- public Player(string id, string name, string model, bool connected, bool poweredOn, bool canPowerOff)
897+ Player(string id)
898 {
899 this.id = id;
900- this.name = name;
901- this.model = model;
902- this.connected = connected;
903- this.poweredOn = poweredOn;
904- this.canPowerOff = canPowerOff;
905 this.syncedWith = new List<Player> ();
906- //Console.WriteLine( "Created: " + name);
907 }
908
909 public string Id
910@@ -45,20 +98,19 @@
911 get {
912 return id;
913 }
914- }
915-
916+ }
917+
918 public override string Name
919 {
920 get {
921 return name;
922 }
923 }
924-
925-
926+
927 public override string Icon
928 {
929 get {
930- return (this.poweredOn ? "SB_on" : "SB_off") + ".png@" + this.GetType ().Assembly.FullName;
931+ return (this.PoweredOn ? "SB_on" : "SB_off") + ".png@" + this.GetType ().Assembly.FullName;
932 }
933 }
934
935@@ -70,18 +122,24 @@
936
937 return string.Format("{0} ({1}){2}",
938 this.model,
939- this.poweredOn ? "On" : "Off",
940+ this.PoweredOn ? "On" : "Off",
941 syncStr == null ? string.Empty : " synced with " + syncStr);
942 }
943 }
944
945 public bool PoweredOn
946 {
947- get {
948- return this.poweredOn;
949- }
950- set {
951- this.poweredOn = value;
952+ get {
953+
954+ switch (this.status)
955+ {
956+ case PlayerStatus.Disconnected:
957+ case PlayerStatus.TurnedOff:
958+ return false;
959+
960+ default :
961+ return true;
962+ }
963 }
964 }
965
966@@ -94,14 +152,14 @@
967 this.canPowerOff = value;
968 }
969 }
970-
971- public bool Connected
972+
973+ public PlayerStatus Status
974 {
975 get {
976- return this.connected;
977+ return this.status;
978 }
979 set {
980- this.connected = value;
981+ this.status = value;
982 }
983 }
984
985@@ -136,8 +194,19 @@
986 {
987 get {
988 lock (this.syncedWith)
989- return this.syncedWith.Count > 0;
990+ return this.syncedWith.Any ();
991 }
992- }
993+ }
994+ }
995+
996+ public enum PlayerStatus
997+ {
998+ Disconnected,
999+ TurnedOff,
1000+
1001+ // one of the following means the player is turned on
1002+ Stopped,
1003+ Paused,
1004+ Playing
1005 }
1006 }
1007
1008=== modified file 'SqueezeCenter/src/RadioItem.cs'
1009--- SqueezeCenter/src/RadioItem.cs 2008-12-24 04:37:17 +0000
1010+++ SqueezeCenter/src/RadioItem.cs 2009-07-31 19:40:23 +0000
1011@@ -13,14 +13,12 @@
1012
1013 using System;
1014 using System.Collections.Generic;
1015-
1016-
1017 using Do.Universe;
1018
1019 namespace SqueezeCenter
1020 {
1021
1022- public abstract class RadioItem : Item
1023+ public abstract class RadioItem : SqueezeCenterItem
1024 {
1025 protected RadioSubItem[] children;
1026
1027@@ -39,6 +37,9 @@
1028 {
1029 get { return "radio.png@" + this.GetType ().Assembly.FullName; }
1030 }
1031+
1032+ public override abstract string Name { get; }
1033+ public override abstract string Description { get; }
1034 }
1035
1036 public class RadioSuperItem : RadioItem
1037
1038=== modified file 'SqueezeCenter/src/Server.cs'
1039--- SqueezeCenter/src/Server.cs 2008-12-24 04:37:17 +0000
1040+++ SqueezeCenter/src/Server.cs 2009-07-31 19:40:23 +0000
1041@@ -12,12 +12,13 @@
1042 // along with this program. If not, see <http://www.gnu.org/licenses/>.
1043
1044 /*
1045- * To enable debug outputm add "VERBOSE_OUTPUT" to "define symbols".
1046+ * To enable debug output, add "VERBOSE_OUTPUT" to "define symbols".
1047 *
1048 */
1049
1050 using System;
1051 using System.Net.Sockets;
1052+using System.Net.NetworkInformation;
1053 using System.IO;
1054 using System.Collections;
1055 using System.Collections.Generic;
1056@@ -106,19 +107,18 @@
1057 int cliport, httpport;
1058 List<string> radiosToLoad = new List<string> ();
1059 bool loadInBackground;
1060-
1061+
1062 Queue commandQueue = Queue.Synchronized (new Queue ());
1063
1064 bool playersLoaded, artistAndAlbumsLoaded, radiosLoaded = false;
1065-
1066- Dictionary<string, Player> players = new Dictionary<string,Player>();
1067+
1068 List<RadioSuperItem> radios = new List<RadioSuperItem> ();
1069 List<ArtistMusicItem> artists = new List<ArtistMusicItem> ();
1070 List<AlbumMusicItem> albums = new List<AlbumMusicItem> ();
1071
1072 Dictionary<string, ArtistMusicItem> artistnameToArtistMap = new Dictionary<string, ArtistMusicItem> ();
1073
1074- private Server(string host, int cliport, int httpport, bool loadInBackground, IEnumerable <string> radiosToLoad)
1075+ Server(string host, int cliport, int httpport, bool loadInBackground, IEnumerable <string> radiosToLoad)
1076 {
1077 this.host = host;
1078 this.cliport = cliport;
1079@@ -130,7 +130,7 @@
1080 }
1081 }
1082
1083- private void Initialze ()
1084+ void Initialze ()
1085 {
1086 #if VERBOSE_OUTPUT
1087 Console.WriteLine ("SqueezeCenter: Host: {0} cliPort: {1} httpPort: {2} loadInBackground: {3}",
1088@@ -142,7 +142,8 @@
1089
1090 // wait for max 15 seconds to allow the players and items to be loaded
1091 DateTime continueAt = DateTime.Now.AddSeconds (15);
1092- // wait while players aren't loaded and, if background loading is disabled, artist, albums and radios aren't loaded
1093+
1094+ // wait while players aren't yet loaded and, if background loading is disabled, artist, albums and radios aren't loaded
1095 bool itemsLoaded = false;
1096 while ( DateTime.Now < continueAt && !itemsLoaded)
1097 {
1098@@ -161,7 +162,7 @@
1099 }
1100 }
1101
1102- private void Quit ()
1103+ void Quit ()
1104 {
1105 this.quitThread = true;
1106 // wait 5 seconds for thread to end
1107@@ -171,39 +172,59 @@
1108 this.workThread.Abort ();
1109 }
1110 }
1111-
1112- private void Execute ()
1113- {
1114+
1115+ void Execute ()
1116+ {
1117
1118 AppDomain.CurrentDomain.ProcessExit += delegate(object sender,EventArgs e)
1119 {
1120 Quit ();
1121- };
1122+ };
1123
1124 try
1125 {
1126- TcpClient tcpClient;
1127- NetworkStream stream;
1128+ TcpClient tcpClient = null;
1129+ NetworkStream stream = null;
1130 StreamWriter writer;
1131 NetworkStreamTextReader reader;
1132 string response;
1133+ DateTime dataLastReceivedAt;
1134
1135 while (!quitThread)
1136 {
1137+ // GetIsNetworkAvailable is not yet implementet in mono...
1138+ /*if (!NetworkInterface.GetIsNetworkAvailable())
1139+ {
1140+ Console.WriteLine("Not connected");
1141+ System.Threading.Thread.Sleep(5000);
1142+ continue;
1143+ }
1144+ Console.WriteLine("Connected!");*/
1145+
1146 try
1147 {
1148+ if (tcpClient != null)
1149+ {
1150+ try
1151+ {
1152+ tcpClient.Close();
1153+ if (stream != null) stream.Dispose();
1154+ }
1155+ catch {}
1156+ }
1157 tcpClient = new TcpClient (this.host, this.cliport);
1158 tcpClient.NoDelay = false;
1159 stream = tcpClient.GetStream ();
1160 writer = new StreamWriter (stream);
1161 reader = new NetworkStreamTextReader (stream);
1162+ dataLastReceivedAt = DateTime.Now;
1163 }
1164 catch (Exception)
1165 {
1166- Console.WriteLine ("SqueezeCenter: Error connecting to server {0}:{1}. Retrying in 30 seconds." +
1167+ Console.WriteLine ("SqueezeCenter: Error connecting to server {0}:{1}. Retrying in 10 seconds." +
1168 "You may want to adjust the settings in the SqueezeCenter configuration dialog.",
1169 this.host, this.cliport);
1170- DateTime continueAt = DateTime.Now.AddSeconds (30);
1171+ DateTime continueAt = DateTime.Now.AddSeconds (10);
1172 while (!this.quitThread && DateTime.Now < continueAt)
1173 Thread.Sleep (1000);
1174 continue;
1175@@ -212,11 +233,23 @@
1176 try
1177 {
1178 // subscribe to needed events
1179+ // - this sends a message every 10 seconds. This way we know if the connections is alive
1180+ commandQueue.Enqueue("serverstatus 0 1 subscribe:10");
1181+ // - this messages us when rescan is complete
1182 commandQueue.Enqueue ("subscribe rescan");
1183+ // - this gives us all players
1184 commandQueue.Enqueue ("players 0 100");
1185
1186 while (!quitThread)
1187- {
1188+ {
1189+ /* if (!NetworkInterface.GetIsNetworkAvailable())
1190+ {
1191+ Console.WriteLine("Not connected 2");
1192+ System.Threading.Thread.Sleep(5000);
1193+ continue;
1194+ }
1195+ Console.WriteLine("Connected 2!");*/
1196+
1197 while ( commandQueue.Count > 0)
1198 {
1199 #if VERBOSE_OUTPUT
1200@@ -229,14 +262,22 @@
1201 if ((response = reader.ReadLine ()) != null)
1202 {
1203 // data received
1204+ dataLastReceivedAt = DateTime.Now;
1205 ParseResponse (response);
1206 response = null;
1207 }
1208 else
1209- {
1210+ {
1211+ // check if connection was lost (serverstatus not received)
1212+ if (DateTime.Now.Subtract(dataLastReceivedAt).TotalSeconds >= 25)
1213+ {
1214+ Console.WriteLine("SQC: serverstatus timeout");
1215+ throw new SocketException();
1216+ }
1217 Thread.Sleep(100);
1218 }
1219- }
1220+
1221+ }
1222
1223 // quit
1224 try
1225@@ -253,16 +294,19 @@
1226 catch (ThreadAbortException) { throw; }
1227 catch (Exception ex)
1228 {
1229- ClearData ();
1230- if (ex is IOException || ex is SocketException)
1231- {
1232- Console.WriteLine ("SqueezeCenter: Connection lost. Trying to reconnect in 5 seconds...");
1233- Thread.Sleep (5000);
1234- }
1235- else
1236- {
1237- Console.WriteLine ("SqueezeCenter unhandled {0}: {1}", ex.GetType ().ToString (), ex.Message);
1238- return;
1239+ SetAllNotAvailable ();
1240+ if (!this.quitThread)
1241+ {
1242+ if (ex is IOException || ex is SocketException)
1243+ {
1244+ Console.WriteLine ("SqueezeCenter: Connection lost. Trying to reconnect in 5 seconds...");
1245+ Thread.Sleep (5000);
1246+ }
1247+ else
1248+ {
1249+ Console.WriteLine ("SqueezeCenter unhandled {0}: {1}", ex.GetType ().ToString (), ex.Message);
1250+ return;
1251+ }
1252 }
1253 }
1254 }
1255@@ -271,55 +315,51 @@
1256 {
1257 }
1258 }
1259-
1260- private void ClearData ()
1261- {
1262- lock (this.players)
1263- this.players.Clear ();
1264+
1265+ /// <summary>
1266+ /// Sets all items to "Not available".
1267+ /// Should be called when there's no connection to the server.
1268+ /// </summary>
1269+ void SetAllNotAvailable ()
1270+ {
1271+ foreach(Player p in Player.GetAllPlayers ())
1272+ p.Available = false;
1273
1274 lock (this.artists)
1275- this.artists.Clear ();
1276+ foreach(MusicItem a in this.artists)
1277+ a.Available = false;
1278
1279 lock (this.albums)
1280- this.albums.Clear ();
1281+ foreach(MusicItem a in this.albums)
1282+ a.Available = false;
1283
1284 lock (this.radios)
1285- this.radios.Clear ();
1286+ foreach(RadioSuperItem r in this.radios)
1287+ r.Available = false;
1288 }
1289
1290- private void ParseResponse (string response)
1291+ void ParseResponse (string response)
1292 {
1293- string head = response.Substring(0, Math.Max(0, response.IndexOf(' ')));
1294+ string head = response.Substring(0, Math.Max(0, response.IndexOf(' ')));
1295
1296 if (string.Equals (head, "players"))
1297 {
1298
1299- // parse players
1300- lock (players) {
1301+ // parse players
1302
1303- foreach (QueryResponseItem itm in ParseQueryResponse
1304- ("playerindex", response, new string[] {"playerid", "name", "model", "connected", "canpoweroff"}))
1305- {
1306-
1307- Player player;
1308- if (players.TryGetValue(itm.Values[0], out player))
1309- {
1310- player.Connected = itm.Values[3] == "1";
1311- player.CanPowerOff = itm.Values[4] == "1";
1312- }
1313- else
1314- {
1315- players.Add (itm.Values[0], new Player (itm.Values[0], itm.Values[1], itm.Values[2],
1316- itm.Values[3] == "1", false, itm.Values[4] == "1"));
1317- }
1318- }
1319-
1320- // get status for all players
1321- foreach (Player p in players.Values)
1322- {
1323- commandQueue.Enqueue(p.Id + " status - 0 subscribe:0");
1324- }
1325+ foreach (QueryResponseItem itm in ParseQueryResponse
1326+ ("playerindex", response, new string[] {"playerid", "name", "model", "connected", "canpoweroff"}))
1327+ {
1328+
1329+ Player.CreatePlayer (itm.Values[0], itm.Values[1], itm.Values[2],
1330+ itm.Values[3] == "1", false, itm.Values[4] == "1");
1331 }
1332+
1333+ // get status for all players
1334+ foreach (Player p in Player.GetAllPlayers ())
1335+ {
1336+ commandQueue.Enqueue(p.Id + " status - 0 subscribe:0");
1337+ }
1338
1339 this.playersLoaded = true;
1340
1341@@ -415,145 +455,165 @@
1342 {
1343
1344 // check if it's a player
1345- Player player;
1346- lock (this.players)
1347- {
1348- if (!players.TryGetValue (Util.UriDecode (head), out player))
1349- {
1350- player = null;
1351- }
1352- }
1353+ Player player = Player.GetFromId(Util.UriDecode (head));
1354
1355 if (player != null && response.Length > head.Length + 1)
1356- {
1357- lock (this.players)
1358- {
1359- response = response.Substring (head.Length +1);
1360- int i = response.IndexOf (' ');
1361- if (i<0)
1362- i = response.Length;
1363- string command = response.Substring (0, i);
1364-
1365+ {
1366+ response = response.Substring (head.Length +1);
1367+ int i = response.IndexOf (' ');
1368+ if (i<0)
1369+ i = response.Length;
1370+ string command = response.Substring (0, i);
1371+
1372 #if VERBOSE_OUTPUT
1373- Console.WriteLine ("SQC: Player command response: " + command);
1374+ Console.WriteLine ("SQC: Player command response: " + command);
1375 #endif
1376-
1377- if (string.Equals (command, "status"))
1378- {
1379- foreach (QueryResponseItem itm in
1380- ParseQueryResponse ("player_name", response,
1381- new string[] {
1382- "player_connected", "power", "sync_master", "sync_slaves" }))
1383- {
1384- player.Connected = itm.Values[0] == "1";
1385- player.PoweredOn = itm.Values[1] == "1";
1386-
1387- // get players that are synced with this player
1388- List<Player> syncedPlayers = new List<Player> ();
1389+
1390+ if (string.Equals (command, "status"))
1391+ {
1392+ var parsedResponse =
1393+ ParseQueryResponse ("player_name", response,
1394+ new string[] {
1395+ "player_connected", "power",
1396+ "sync_master", "sync_slaves", "mode" });
1397
1398- if (itm.Values[2] != null && itm.Values[3] != null)
1399- {
1400- string playersInSyncGroup = string.Format ("{0},{1}", itm.Values[2], itm.Values[3]);
1401- foreach (string s in playersInSyncGroup.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
1402- {
1403- Player p;
1404- if (this.players.TryGetValue (s.Trim (), out p) && p != player)
1405- {
1406- syncedPlayers.Add (p);
1407- }
1408- }
1409- }
1410- // due to bug http://bugs.slimdevices.com/show_bug.cgi?id=7990
1411- // we need to get the status of all players that are now unsynced
1412- // BEGIN workaround
1413- foreach (Player p in player.SyncedPlayers)
1414- {
1415- if (!syncedPlayers.Contains (p))
1416- {
1417- commandQueue.Enqueue(p.Id + " status - 0");
1418- }
1419- }
1420- // END workaround
1421- player.SetSynchedPlayers (syncedPlayers);
1422- }
1423+ foreach (QueryResponseItem itm in parsedResponse)
1424+ {
1425+ // find status
1426+ bool isConnected = itm.Values[0] == "1";
1427+ bool isPoweredOn = itm.Values[1] == "1";
1428+ string mode = itm.Values[4];
1429+ PlayerStatus status;
1430+
1431+ if (!isConnected)
1432+ status = PlayerStatus.Disconnected;
1433+ else {
1434+ if (!isPoweredOn)
1435+ status = PlayerStatus.TurnedOff;
1436+ else {
1437+ // parse mode
1438+ switch (mode) {
1439+ case "play":
1440+ status = PlayerStatus.Playing;
1441+ break;
1442+
1443+ case "pause" :
1444+ status = PlayerStatus.Paused;
1445+ break;
1446+
1447+ default:
1448+ status = PlayerStatus.Stopped;
1449+ break;
1450+ }
1451+ }
1452+ }
1453+
1454+ player.Status = status;
1455+
1456+
1457+ // get players that are synced with this player
1458+ List<Player> syncedPlayers = new List<Player> ();
1459+
1460+ if (itm.Values[2] != null && itm.Values[3] != null)
1461+ {
1462+ string playersInSyncGroup = string.Format ("{0},{1}", itm.Values[2], itm.Values[3]);
1463+ foreach (string s in playersInSyncGroup.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries))
1464+ {
1465+ Player p = Player.GetFromId(s.Trim ());
1466+ if (p != null && p != player)
1467+ syncedPlayers.Add (p);
1468+ }
1469+ }
1470+ // due to bug http://bugs.slimdevices.com/show_bug.cgi?id=7990
1471+ // we need to get the status of all players that are now unsynced
1472+ // BEGIN workaround
1473+ foreach (Player p in player.SyncedPlayers)
1474+ {
1475+ if (!syncedPlayers.Contains (p))
1476+ {
1477+ commandQueue.Enqueue(p.Id + " status - 0");
1478+ }
1479+ }
1480+ // END workaround
1481+ player.SetSynchedPlayers (syncedPlayers);
1482 }
1483+ }
1484+
1485+ else
1486+ {
1487+ // check if it's a radio
1488+ RadioSuperItem radio = null;
1489
1490- else
1491+ lock (this.radios)
1492 {
1493- // check if it's a radio
1494- RadioSuperItem radio = null;
1495-
1496- lock (this.radios)
1497- {
1498- foreach (RadioSuperItem r in this.radios) {
1499- if (response.StartsWith (r.Command + " items ")) {
1500- radio = r;
1501- break;
1502- }
1503- }
1504- }
1505-
1506- if (radio != null) {
1507- // get position of content start
1508- int pos = response.IndexOf ("item_id%3A");
1509- if (pos < 0)
1510- pos = response.IndexOf ("title%3A");
1511-
1512- if (pos > 0)
1513- {
1514- string ids;
1515- int id;
1516- List <RadioSubItem> children;
1517- RadioSubItem child;
1518-
1519- // find parent
1520- RadioItem parent = radio;
1521-
1522- // is there a item_id filter?
1523- if (response.Substring (pos).StartsWith ("item_id%3A")) {
1524- ids = response.Substring (pos+10, response.IndexOf (" ", pos+10) - pos - 10);
1525-
1526- foreach (string subId in ids.Split (new char[] {'.'})) {
1527- foreach (RadioSubItem rmi in parent.Children) {
1528- if (rmi.Id.ToString() == subId) {
1529- parent = rmi;
1530- break;
1531- }
1532- }
1533- }
1534- }
1535- //Console.WriteLine (response);
1536- children = new List<RadioSubItem> ();
1537-
1538- foreach (QueryResponseItem itm in
1539- ParseQueryResponse ("id", response, new string[] {
1540- "id", "hasitems", "name"})) {
1541-
1542- ids = itm.Values[0];
1543- if (parent is RadioSubItem && ids == (parent as RadioSubItem).IdPath) {
1544- continue;
1545- }
1546-
1547- if (ids.Contains ("."))
1548- ids = ids.Substring (ids.LastIndexOf (".")+1);
1549-
1550- if (int.TryParse (ids, out id) && itm.Values[2] != null) {
1551- child = new RadioSubItem (parent, id, itm.Values[2], itm.Values[1] != null && itm.Values[1] != "0");
1552- children.Add (child);
1553+ foreach (RadioSuperItem r in this.radios) {
1554+ if (response.StartsWith (r.Command + " items ")) {
1555+ radio = r;
1556+ break;
1557+ }
1558+ }
1559+ }
1560
1561- // request children
1562- if (child.HasItems) {
1563- commandQueue.Enqueue (string.Format ("{0} items 0 10000 item_id:{1}",
1564- child.GetSuper ().Command,
1565- child.IdPath ));
1566+ if (radio != null) {
1567+ // get position of content start
1568+ int pos = response.IndexOf ("item_id%3A");
1569+ if (pos < 0)
1570+ pos = response.IndexOf ("title%3A");
1571+
1572+ if (pos > 0)
1573+ {
1574+ string ids;
1575+ int id;
1576+ List <RadioSubItem> children;
1577+ RadioSubItem child;
1578+
1579+ // find parent
1580+ RadioItem parent = radio;
1581+
1582+ // is there a item_id filter?
1583+ if (response.Substring (pos).StartsWith ("item_id%3A")) {
1584+ ids = response.Substring (pos+10, response.IndexOf (" ", pos+10) - pos - 10);
1585+
1586+ foreach (string subId in ids.Split (new char[] {'.'})) {
1587+ foreach (RadioSubItem rmi in parent.Children) {
1588+ if (rmi.Id.ToString() == subId) {
1589+ parent = rmi;
1590+ break;
1591 }
1592 }
1593- }
1594- parent.Children = children.ToArray ();
1595- }
1596- }
1597+ }
1598+ }
1599+ //Console.WriteLine (response);
1600+ children = new List<RadioSubItem> ();
1601+
1602+ foreach (QueryResponseItem itm in
1603+ ParseQueryResponse ("id", response, new string[] {
1604+ "id", "hasitems", "name"})) {
1605+
1606+ ids = itm.Values[0];
1607+ if (parent is RadioSubItem && ids == (parent as RadioSubItem).IdPath) {
1608+ continue;
1609+ }
1610+
1611+ if (ids.Contains ("."))
1612+ ids = ids.Substring (ids.LastIndexOf (".")+1);
1613+
1614+ if (int.TryParse (ids, out id) && itm.Values[2] != null) {
1615+ child = new RadioSubItem (parent, id, itm.Values[2], itm.Values[1] != null && itm.Values[1] != "0");
1616+ children.Add (child);
1617+
1618+ // request children
1619+ if (child.HasItems) {
1620+ commandQueue.Enqueue (string.Format ("{0} items 0 10000 item_id:{1}",
1621+ child.GetSuper ().Command,
1622+ child.IdPath ));
1623+ }
1624+ }
1625+ }
1626+ parent.Children = children.ToArray ();
1627+ }
1628 }
1629- }
1630+ }
1631 }
1632 }
1633 }
1634@@ -577,38 +637,7 @@
1635 lock (this.radios) {
1636 return this.radios.ToArray ();
1637 }
1638- }
1639-
1640- public Player[] GetPlayers ()
1641- {
1642- lock (players) {
1643- Player[] result = new Player[players.Count];
1644- players.Values.CopyTo (result, 0);
1645- return result;
1646- }
1647- }
1648-
1649- public List<Player> GetConnectedPlayers ()
1650- {
1651- lock (players) {
1652- List<Player> result = new List<Player> (players.Count);
1653- foreach (Player p in players.Values)
1654- if (p.Connected)
1655- result.Add (p);
1656- return result;
1657- }
1658- }
1659-
1660- public List<Do.Universe.Item> GetConnectedPlayersAsItem ()
1661- {
1662- lock (players) {
1663- List<Do.Universe.Item> result = new List<Do.Universe.Item> (players.Count);
1664- foreach (Player p in players.Values)
1665- if (p.Connected)
1666- result.Add (p);
1667- return result;
1668- }
1669- }
1670+ }
1671
1672 public void ExecuteCommand(string command)
1673 {
1674@@ -630,7 +659,7 @@
1675 return string.Format ("http://{0}:{1}/music/{2}/cover.jpg", this.host, this.httpport, songId);
1676 }
1677
1678- private bool IsRadioLoaded ()
1679+ bool IsRadioLoaded ()
1680 {
1681 if (!this.radiosLoaded)
1682 return false;
1683@@ -645,7 +674,7 @@
1684 return true;
1685 }
1686
1687- private void PlaylistControl(Player player, IEnumerable<MusicItem> items, string command)
1688+ void PlaylistControl(Player player, IEnumerable<MusicItem> items, string command)
1689 {
1690 foreach (MusicItem item in items) {
1691 string cmd = string.Format ("{0} playlistcontrol cmd:{1} {2}:{3}",
1692@@ -654,7 +683,7 @@
1693 }
1694 }
1695
1696- private List<QueryResponseItem> ParseQueryResponse (string seperatorTag, string resp, string[] fields)
1697+ List<QueryResponseItem> ParseQueryResponse (string seperatorTag, string resp, string[] fields)
1698 {
1699 List<QueryResponseItem> result = new List<QueryResponseItem>();
1700
1701@@ -682,8 +711,7 @@
1702
1703 int fieldIdx = Array.IndexOf(fields, tagName);
1704 if(fieldIdx >= 0)
1705- {
1706- //respItm.Values[fieldIdx] = System.Web.HttpUtility.UrlDecode (fieldValue);
1707+ {
1708 respItm.Values[fieldIdx] = Util.UriDecode (fieldValue);
1709 }
1710
1711@@ -696,7 +724,7 @@
1712 return result;
1713 }
1714
1715- private class QueryResponseItem
1716+ class QueryResponseItem
1717 {
1718 public QueryResponseItem(int valuesCount)
1719 {
1720
1721=== modified file 'SqueezeCenter/src/Settings.cs'
1722--- SqueezeCenter/src/Settings.cs 2008-12-24 04:37:17 +0000
1723+++ SqueezeCenter/src/Settings.cs 2009-07-31 19:40:23 +0000
1724@@ -24,6 +24,7 @@
1725
1726 public static void ReadSettings (string filename, ICollection<Setting> settings, bool storeMissingValues)
1727 {
1728+ Console.WriteLine("Reading settings from " + filename);
1729
1730 string line, key, val;
1731 int i;
1732
1733=== added file 'SqueezeCenter/src/SqueezeCenterItem.cs'
1734--- SqueezeCenter/src/SqueezeCenterItem.cs 1970-01-01 00:00:00 +0000
1735+++ SqueezeCenter/src/SqueezeCenterItem.cs 2009-07-31 19:40:23 +0000
1736@@ -0,0 +1,41 @@
1737+// ISqueezeCenterItem.cs created with MonoDevelop
1738+// User: anders at 13:06 11-12-2008
1739+//
1740+//// This program is free software: you can redistribute it and/or modify
1741+//// it under the terms of the GNU General Public License as published by
1742+//// the Free Software Foundation, either version 3 of the License, or
1743+//// (at your option) any later version.
1744+////
1745+//// This program is distributed in the hope that it will be useful,
1746+//// but WITHOUT ANY WARRANTY; without even the implied warranty of
1747+//// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1748+//// GNU General Public License for more details.
1749+////
1750+//// You should have received a copy of the GNU General Public License
1751+//// along with this program. If not, see <http://www.gnu.org/licenses/>.
1752+
1753+using System;
1754+using Do.Universe;
1755+
1756+namespace SqueezeCenter
1757+{
1758+
1759+ public abstract class SqueezeCenterItem : Do.Universe.Item
1760+ {
1761+ public SqueezeCenterItem()
1762+ {
1763+ }
1764+
1765+ bool available = true;
1766+ public bool Available
1767+ {
1768+ get { return this.available; }
1769+ set { this.available = value; }
1770+ }
1771+
1772+ public override abstract string Name { get; }
1773+ public override abstract string Icon { get; }
1774+ public override abstract string Description { get; }
1775+
1776+ }
1777+}
1778
1779=== modified file 'SqueezeCenter/src/Util.cs'
1780--- SqueezeCenter/src/Util.cs 2008-12-24 04:37:17 +0000
1781+++ SqueezeCenter/src/Util.cs 2009-07-31 19:40:23 +0000
1782@@ -18,12 +18,7 @@
1783 {
1784 public static class Util
1785 {
1786- public static IEnumerable<Ttarget> Cast<Tsource, Ttarget> (IEnumerable<Tsource> items)
1787- {
1788- foreach (object i in items)
1789- yield return (Ttarget)i;
1790- }
1791-
1792+
1793 public static string UriDecode (string s)
1794 {
1795 int i = 0;

Subscribers

People subscribed via source and target branches