Merge lp:~urbanape/ubuntuone-ios-client/all-albums-view into lp:ubuntuone-ios-client

Proposed by Zachery Bir
Status: Merged
Approved by: Zachery Bir
Approved revision: 226
Merge reported by: Zachery Bir
Merged at revision: not available
Proposed branch: lp:~urbanape/ubuntuone-ios-client/all-albums-view
Merge into: lp:ubuntuone-ios-client
Diff against target: 2091 lines (+1058/-189)
42 files modified
musicstreaming/Other Sources/iSubAppDelegate.m (+19/-18)
musicstreaming/categories/NSMutableSet+Extras.h (+26/-0)
musicstreaming/categories/NSMutableSet+Extras.m (+57/-0)
musicstreaming/controls/AlertPrompt.h (+29/-0)
musicstreaming/controls/AlertPrompt.m (+58/-0)
musicstreaming/iSub.xcodeproj/project.pbxproj (+36/-6)
musicstreaming/models/Album.m (+6/-8)
musicstreaming/models/Playlist.h (+4/-4)
musicstreaming/models/Playlist.m (+22/-5)
musicstreaming/models/Song.m (+27/-25)
musicstreaming/utilities/AlbumListParser.h (+37/-0)
musicstreaming/utilities/AlbumListParser.m (+98/-0)
musicstreaming/utilities/AlbumParser.h (+27/-0)
musicstreaming/utilities/AlbumParser.m (+64/-0)
musicstreaming/utilities/ArtistListParser.h (+2/-2)
musicstreaming/utilities/ArtistParser.h (+2/-2)
musicstreaming/utilities/ArtistParser.m (+3/-3)
musicstreaming/utilities/PlaylistListParser.h (+1/-1)
musicstreaming/utilities/PlaylistListParser.m (+1/-1)
musicstreaming/utilities/PlaylistParser.h (+6/-6)
musicstreaming/utilities/PlaylistParser.m (+10/-9)
musicstreaming/utilities/SongListParser.h (+2/-2)
musicstreaming/utilities/StreamingPlayer.m (+3/-3)
musicstreaming/utilities/Subsonic.h (+2/-2)
musicstreaming/utilities/Subsonic.m (+13/-11)
musicstreaming/view_controllers/AlbumListViewController.m (+124/-0)
musicstreaming/view_controllers/AlbumViewController.h (+2/-2)
musicstreaming/view_controllers/AlbumViewController.m (+7/-5)
musicstreaming/view_controllers/ArtistListViewController.m (+2/-2)
musicstreaming/view_controllers/ArtistViewController.m (+12/-19)
musicstreaming/view_controllers/PlaylistEditViewController.h (+36/-0)
musicstreaming/view_controllers/PlaylistEditViewController.m (+214/-0)
musicstreaming/view_controllers/PlaylistListViewController.m (+58/-8)
musicstreaming/view_controllers/PlaylistViewController.m (+24/-16)
musicstreaming/view_controllers/SettingsViewController.h (+1/-3)
musicstreaming/view_controllers/SettingsViewController.m (+2/-9)
musicstreaming/view_controllers/SongListViewController.m (+3/-3)
musicstreaming/view_controllers/SongViewController.m (+6/-2)
musicstreaming/view_controllers/SubsonicIndexedTableViewController.h (+1/-1)
musicstreaming/view_controllers/SubsonicIndexedTableViewController.m (+1/-3)
musicstreaming/view_controllers/SubsonicTableViewController.h (+4/-3)
musicstreaming/view_controllers/SubsonicTableViewController.m (+6/-5)
To merge this branch: bzr merge lp:~urbanape/ubuntuone-ios-client/all-albums-view
Reviewer Review Type Date Requested Status
Aaron Brethorst (community) Approve
Review via email: mp+56868@code.launchpad.net

Description of the change

This branch provides a client-side view for navigating all albums. It still needs a little work from the server side, but the albums are navigable.

To post a comment you must log in.
Revision history for this message
Aaron Brethorst (aaronbrethorst-deactivatedaccount) wrote :

AlbumParser.m - should probably report errors to a delegate, which should in turn decide how to report errors instead of directly showing a UIAlertView. Better to remove UI presentation details from the parser. Use case: porting U1 Music to OS X will require you to use an NSAlert instead of a UIAlertView.

PlaylistEditViewController.m - + (UINavigationController *)navigableViewControllerWithPlaylist:(Playlist *)playlist delegate:(id)delegate -- the delegate parameter seems misleading, since it looks like delegate can only actually be a specific type (PlaylistListViewController). Instead, that parameter's type should probably just be a PlaylistListViewController*.

PlaylistListViewController.m - In - (void)alertView:(UIAlertView *)alertPrompt clickedButtonAtIndex:(NSInteger)buttonIndex, check for alertPrompt.cancelButtonIndex instead of looking for a magic value (1).

review: Approve
225. By Zachery Bir

Cleanup suggested by Aaron

226. By Zachery Bir

Normalized ID->Id, cleaned up some missing parameters work, and wrapped a parameter as a string

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'musicstreaming/Other Sources/iSubAppDelegate.m'
2--- musicstreaming/Other Sources/iSubAppDelegate.m 2011-04-01 03:07:39 +0000
3+++ musicstreaming/Other Sources/iSubAppDelegate.m 2011-04-08 19:49:28 +0000
4@@ -78,24 +78,25 @@
5 UINavigationController *nav = nil;
6 NSMutableArray *viewControllers = [NSMutableArray array];
7
8- ArtistListViewController *artistListViewController = [[ArtistListViewController alloc] initWithTitle:NSLocalizedString(@"Artists", @"")];
9- nav = [[UINavigationController alloc] initWithRootViewController:artistListViewController];
10- [viewControllers addObject:nav];
11-
12- AlbumListViewController *albumListViewController = [[AlbumListViewController alloc] initWithTitle:NSLocalizedString(@"Albums", @"")];
13- nav = [[UINavigationController alloc] initWithRootViewController:albumListViewController];
14- [viewControllers addObject:nav];
15-
16- SongListViewController *songListViewController = [[SongListViewController alloc] initWithTitle:NSLocalizedString(@"Songs", @"")];
17- nav = [[UINavigationController alloc] initWithRootViewController:songListViewController];
18- [viewControllers addObject:nav];
19-
20- PlaylistListViewController *playlistListViewController = [[PlaylistListViewController alloc] initWithTitle:NSLocalizedString(@"Playlists", @"")];
21- nav = [[UINavigationController alloc] initWithRootViewController:playlistListViewController];
22- [viewControllers addObject:nav];
23-
24- SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped];
25- nav = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
26+ ArtistListViewController *artistListViewController = [[[ArtistListViewController alloc] initWithTitle:NSLocalizedString(@"Artists", @"")] autorelease];
27+ nav = [[[UINavigationController alloc] initWithRootViewController:artistListViewController] autorelease];
28+ [viewControllers addObject:nav];
29+
30+ AlbumListViewController *albumListViewController = [[[AlbumListViewController alloc] initWithTitle:NSLocalizedString(@"Albums", @"")] autorelease];
31+ nav = [[[UINavigationController alloc] initWithRootViewController:albumListViewController] autorelease];
32+ [viewControllers addObject:nav];
33+
34+ SongListViewController *songListViewController = [[[SongListViewController alloc] initWithTitle:NSLocalizedString(@"Songs", @"")] autorelease];
35+ nav = [[[UINavigationController alloc] initWithRootViewController:songListViewController] autorelease];
36+ [viewControllers addObject:nav];
37+
38+ PlaylistListViewController *playlistListViewController = [[[PlaylistListViewController alloc] initWithTitle:NSLocalizedString(@"Playlists", @"")] autorelease];
39+ nav = [[[UINavigationController alloc] initWithRootViewController:playlistListViewController] autorelease];
40+ [viewControllers addObject:nav];
41+
42+ SettingsViewController *settingsViewController = [[[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
43+ nav = [[[UINavigationController alloc] initWithRootViewController:settingsViewController] autorelease];
44+ nav.navigationBar.barStyle = UIBarStyleBlack;
45 [viewControllers addObject:nav];
46
47 [tabBarController setViewControllers:viewControllers animated:YES];
48
49=== added file 'musicstreaming/categories/NSMutableSet+Extras.h'
50--- musicstreaming/categories/NSMutableSet+Extras.h 1970-01-01 00:00:00 +0000
51+++ musicstreaming/categories/NSMutableSet+Extras.h 2011-04-08 19:49:28 +0000
52@@ -0,0 +1,26 @@
53+//
54+// NSMutableSet+Extras.h
55+// iSub
56+//
57+// Created by Zachery Bir on 4/7/11.
58+// Copyright 2011 Canonical Ltd.
59+//
60+// This program is free software: you can redistribute it and/or modify it
61+// under the terms of the GNU Affero General Public License version 3,
62+// as published by the Free Software Foundation.
63+//
64+// This program is distributed in the hope that it will be useful, but
65+// WITHOUT ANY WARRANTY; without even the implied warranties of
66+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
67+// PURPOSE. See the GNU Affero General Public License for more details.
68+//
69+// You should have received a copy of the GNU Affero General Public License
70+// along with this program. If not, see <http://www.gnu.org/licenses/>.
71+
72+#import <Foundation/Foundation.h>
73+
74+
75+@interface NSMutableSet (Extras)
76+- (void)addKeyValueObjectFromArray:(NSArray *)array;
77+- (NSString*)urlEncodedString;
78+@end
79
80=== added file 'musicstreaming/categories/NSMutableSet+Extras.m'
81--- musicstreaming/categories/NSMutableSet+Extras.m 1970-01-01 00:00:00 +0000
82+++ musicstreaming/categories/NSMutableSet+Extras.m 2011-04-08 19:49:28 +0000
83@@ -0,0 +1,57 @@
84+//
85+// NSMutableSet+Extras.m
86+// iSub
87+//
88+// Created by Zachery Bir on 4/7/11.
89+// Copyright 2011 Canonical Ltd.
90+//
91+// This program is free software: you can redistribute it and/or modify it
92+// under the terms of the GNU Affero General Public License version 3,
93+// as published by the Free Software Foundation.
94+//
95+// This program is distributed in the hope that it will be useful, but
96+// WITHOUT ANY WARRANTY; without even the implied warranties of
97+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
98+// PURPOSE. See the GNU Affero General Public License for more details.
99+//
100+// You should have received a copy of the GNU Affero General Public License
101+// along with this program. If not, see <http://www.gnu.org/licenses/>.
102+
103+#import "NSMutableSet+Extras.h"
104+
105+// helper function: get the string form of any object
106+static NSString *toString(id object)
107+{
108+ return [NSString stringWithFormat: @"%@", object];
109+}
110+
111+// helper function: get the url encoded string form of any object
112+static NSString *urlEncode(id object)
113+{
114+ NSString *string = toString(object);
115+ return [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
116+}
117+
118+@implementation NSMutableSet (Extras)
119+
120+- (void)addKeyValueObjectFromArray:(NSArray *)array
121+{
122+ [self addObject:[NSDictionary dictionaryWithObjects:array
123+ forKeys:[NSArray arrayWithObjects:@"key", @"value", nil]]];
124+}
125+
126+- (NSString*)urlEncodedString
127+{
128+ NSMutableArray *parts = [NSMutableArray array];
129+
130+ for (id object in self)
131+ {
132+ id key = [object objectForKey:@"key"];
133+ id value = [object objectForKey:@"value"];
134+ NSString *part = [NSString stringWithFormat:@"%@=%@",urlEncode(key),urlEncode(value)];
135+ [parts addObject:part];
136+ }
137+ return [parts componentsJoinedByString:@"&"];
138+}
139+
140+@end
141
142=== added file 'musicstreaming/controls/AlertPrompt.h'
143--- musicstreaming/controls/AlertPrompt.h 1970-01-01 00:00:00 +0000
144+++ musicstreaming/controls/AlertPrompt.h 2011-04-08 19:49:28 +0000
145@@ -0,0 +1,29 @@
146+//
147+// AlertPrompt.h
148+// iSub
149+//
150+// Created by Zachery Bir on 4/4/11.
151+// Copyright 2011 Canonical Ltd.
152+//
153+// This program is free software: you can redistribute it and/or modify it
154+// under the terms of the GNU Affero General Public License version 3,
155+// as published by the Free Software Foundation.
156+//
157+// This program is distributed in the hope that it will be useful, but
158+// WITHOUT ANY WARRANTY; without even the implied warranties of
159+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
160+// PURPOSE. See the GNU Affero General Public License for more details.
161+//
162+// You should have received a copy of the GNU Affero General Public License
163+// along with this program. If not, see <http://www.gnu.org/licenses/>.
164+
165+#import <Foundation/Foundation.h>
166+
167+@interface AlertPrompt : UIAlertView
168+{
169+ UITextField *textField;
170+}
171+@property (nonatomic, retain) UITextField *textField;
172+@property (readonly) NSString *enteredText;
173+- (id)initWithTitle:(NSString *)title placeholder:(NSString *)placeholder message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okButtonTitle;
174+@end
175
176=== added file 'musicstreaming/controls/AlertPrompt.m'
177--- musicstreaming/controls/AlertPrompt.m 1970-01-01 00:00:00 +0000
178+++ musicstreaming/controls/AlertPrompt.m 2011-04-08 19:49:28 +0000
179@@ -0,0 +1,58 @@
180+//
181+// AlertPrompt.m
182+// iSub
183+//
184+// Created by Zachery Bir on 4/4/11.
185+// Copyright 2011 Canonical Ltd.
186+//
187+// This program is free software: you can redistribute it and/or modify it
188+// under the terms of the GNU Affero General Public License version 3,
189+// as published by the Free Software Foundation.
190+//
191+// This program is distributed in the hope that it will be useful, but
192+// WITHOUT ANY WARRANTY; without even the implied warranties of
193+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
194+// PURPOSE. See the GNU Affero General Public License for more details.
195+//
196+// You should have received a copy of the GNU Affero General Public License
197+// along with this program. If not, see <http://www.gnu.org/licenses/>.
198+
199+#import "AlertPrompt.h"
200+
201+@implementation AlertPrompt
202+@synthesize textField;
203+@synthesize enteredText;
204+
205+- (id)initWithTitle:(NSString *)title placeholder:(NSString *)placeholder message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle okButtonTitle:(NSString *)okayButtonTitle
206+{
207+
208+ if ((self = [super initWithTitle:title message:message delegate:delegate cancelButtonTitle:cancelButtonTitle otherButtonTitles:okayButtonTitle, nil]))
209+ {
210+ UITextField *theTextField = [[UITextField alloc] initWithFrame:CGRectMake(12.0, 45.0, 260.0, 25.0)];
211+ theTextField.placeholder = placeholder;
212+ theTextField.backgroundColor = [UIColor clearColor];
213+ theTextField.borderStyle = UITextBorderStyleRoundedRect;
214+ [self addSubview:theTextField];
215+ self.textField = theTextField;
216+ [theTextField release];
217+ }
218+ return self;
219+}
220+
221+- (void)show
222+{
223+ [textField becomeFirstResponder];
224+ [super show];
225+}
226+
227+- (NSString *)enteredText
228+{
229+ return textField.text;
230+}
231+
232+- (void)dealloc
233+{
234+ [textField release];
235+ [super dealloc];
236+}
237+@end
238
239=== modified file 'musicstreaming/iSub.xcodeproj/project.pbxproj'
240--- musicstreaming/iSub.xcodeproj/project.pbxproj 2011-04-01 14:55:49 +0000
241+++ musicstreaming/iSub.xcodeproj/project.pbxproj 2011-04-08 19:49:28 +0000
242@@ -18,10 +18,15 @@
243 53F675DC113B093900822059 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F675DB113B093900822059 /* CFNetwork.framework */; };
244 53F675E2113B095900822059 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F675E1113B095900822059 /* QuartzCore.framework */; };
245 53F675E8113B096400822059 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 53F675E7113B096400822059 /* AudioToolbox.framework */; };
246+ 9110DC38134C045A0046B8E4 /* AlbumParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9110DC37134C04590046B8E4 /* AlbumParser.m */; };
247+ 9110DC41134E4EEF0046B8E4 /* NSMutableSet+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = 9110DC40134E4EEF0046B8E4 /* NSMutableSet+Extras.m */; };
248+ 9110DC44134EAC740046B8E4 /* AlbumListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9110DC43134EAC730046B8E4 /* AlbumListParser.m */; };
249 9123D1A113257ADF00B40210 /* PlaylistListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9123D1A013257ADF00B40210 /* PlaylistListViewController.m */; };
250 9123D1BB13280B3400B40210 /* PlaylistViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9123D1BA13280B3400B40210 /* PlaylistViewController.m */; };
251 9123D1C3132816D200B40210 /* PlaylistListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 9123D1C2132816D200B40210 /* PlaylistListParser.m */; };
252 912D1259134617F600721EE4 /* SongListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 912D1258134617F600721EE4 /* SongListParser.m */; };
253+ 912D1264134A162000721EE4 /* AlertPrompt.m in Sources */ = {isa = PBXBuildFile; fileRef = 912D1263134A162000721EE4 /* AlertPrompt.m */; };
254+ 912D1267134B609700721EE4 /* PlaylistEditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 912D1266134B609600721EE4 /* PlaylistEditViewController.m */; };
255 912D392213311F2700A443B2 /* AlbumListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 912D392113311F2500A443B2 /* AlbumListViewController.m */; };
256 912D392613311FC600A443B2 /* SongListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 912D392513311FC400A443B2 /* SongListViewController.m */; };
257 91B3A4441344CF92006C8193 /* SubsonicIndexedTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 91B3A4431344CF91006C8193 /* SubsonicIndexedTableViewController.m */; };
258@@ -61,7 +66,7 @@
259 93D6B5151252CB34007880B0 /* music_57@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 93D6B5141252CB34007880B0 /* music_57@2x.png */; };
260 93D6B54B1252CE57007880B0 /* URLQueryStringParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93D6B54A1252CE57007880B0 /* URLQueryStringParser.m */; };
261 93EE2AF0124993F100E7E060 /* ArtistListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93EE2AEF124993F100E7E060 /* ArtistListParser.m */; };
262- 93EE2BA31249F33D00E7E060 /* AlbumListParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93EE2BA21249F33D00E7E060 /* AlbumListParser.m */; };
263+ 93EE2BA31249F33D00E7E060 /* ArtistParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 93EE2BA21249F33D00E7E060 /* ArtistParser.m */; };
264 93F334471247F9DE006C6707 /* SFHFKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 93F334461247F9DE006C6707 /* SFHFKeychainUtils.m */; };
265 93F3344D1247FA0B006C6707 /* Reachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 93F3344C1247FA0B006C6707 /* Reachability.m */; };
266 93F334521247FA2C006C6707 /* Album.m in Sources */ = {isa = PBXBuildFile; fileRef = 93F3344F1247FA2C006C6707 /* Album.m */; };
267@@ -112,6 +117,12 @@
268 53F675E1113B095900822059 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
269 53F675E7113B096400822059 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
270 8D1107310486CEB800E47090 /* iSub-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "iSub-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
271+ 9110DC36134C04590046B8E4 /* AlbumParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlbumParser.h; sourceTree = "<group>"; };
272+ 9110DC37134C04590046B8E4 /* AlbumParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlbumParser.m; sourceTree = "<group>"; };
273+ 9110DC3F134E4EEF0046B8E4 /* NSMutableSet+Extras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableSet+Extras.h"; sourceTree = "<group>"; };
274+ 9110DC40134E4EEF0046B8E4 /* NSMutableSet+Extras.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableSet+Extras.m"; sourceTree = "<group>"; };
275+ 9110DC42134EAC720046B8E4 /* AlbumListParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlbumListParser.h; sourceTree = "<group>"; };
276+ 9110DC43134EAC730046B8E4 /* AlbumListParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlbumListParser.m; sourceTree = "<group>"; };
277 9123D19F13257ADF00B40210 /* PlaylistListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistListViewController.h; sourceTree = "<group>"; };
278 9123D1A013257ADF00B40210 /* PlaylistListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistListViewController.m; sourceTree = "<group>"; };
279 9123D1B913280B3400B40210 /* PlaylistViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistViewController.h; sourceTree = "<group>"; };
280@@ -120,6 +131,10 @@
281 9123D1C2132816D200B40210 /* PlaylistListParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistListParser.m; sourceTree = "<group>"; };
282 912D1257134617F600721EE4 /* SongListParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SongListParser.h; sourceTree = "<group>"; };
283 912D1258134617F600721EE4 /* SongListParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SongListParser.m; sourceTree = "<group>"; };
284+ 912D1262134A162000721EE4 /* AlertPrompt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlertPrompt.h; sourceTree = "<group>"; };
285+ 912D1263134A162000721EE4 /* AlertPrompt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlertPrompt.m; sourceTree = "<group>"; };
286+ 912D1265134B609500721EE4 /* PlaylistEditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaylistEditViewController.h; sourceTree = "<group>"; };
287+ 912D1266134B609600721EE4 /* PlaylistEditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlaylistEditViewController.m; sourceTree = "<group>"; };
288 912D392013311F2400A443B2 /* AlbumListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlbumListViewController.h; sourceTree = "<group>"; };
289 912D392113311F2500A443B2 /* AlbumListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlbumListViewController.m; sourceTree = "<group>"; };
290 912D392413311FC400A443B2 /* SongListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SongListViewController.h; sourceTree = "<group>"; };
291@@ -182,8 +197,8 @@
292 93D6B54A1252CE57007880B0 /* URLQueryStringParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = URLQueryStringParser.m; sourceTree = "<group>"; };
293 93EE2AEE124993F100E7E060 /* ArtistListParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArtistListParser.h; sourceTree = "<group>"; };
294 93EE2AEF124993F100E7E060 /* ArtistListParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArtistListParser.m; sourceTree = "<group>"; };
295- 93EE2BA11249F33D00E7E060 /* AlbumListParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlbumListParser.h; sourceTree = "<group>"; };
296- 93EE2BA21249F33D00E7E060 /* AlbumListParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AlbumListParser.m; sourceTree = "<group>"; };
297+ 93EE2BA11249F33D00E7E060 /* ArtistParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArtistParser.h; sourceTree = "<group>"; };
298+ 93EE2BA21249F33D00E7E060 /* ArtistParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArtistParser.m; sourceTree = "<group>"; };
299 93F334451247F9DE006C6707 /* SFHFKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFHFKeychainUtils.h; sourceTree = "<group>"; };
300 93F334461247F9DE006C6707 /* SFHFKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SFHFKeychainUtils.m; sourceTree = "<group>"; };
301 93F3344B1247FA0B006C6707 /* Reachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Reachability.h; sourceTree = "<group>"; };
302@@ -331,6 +346,8 @@
303 93D6B213124F0F62007880B0 /* NSNumber+Extras.m */,
304 93D6B2D1124FDA56007880B0 /* NSMutableArray+Extras.h */,
305 93D6B2D2124FDA56007880B0 /* NSMutableArray+Extras.m */,
306+ 9110DC3F134E4EEF0046B8E4 /* NSMutableSet+Extras.h */,
307+ 9110DC40134E4EEF0046B8E4 /* NSMutableSet+Extras.m */,
308 );
309 path = categories;
310 sourceTree = "<group>";
311@@ -359,6 +376,8 @@
312 936F230912284D1900070F43 /* NamedTextFieldCell.m */,
313 936F1F2F12271B6500070F43 /* MBProgressHUD.h */,
314 936F1F3012271B6500070F43 /* MBProgressHUD.m */,
315+ 912D1262134A162000721EE4 /* AlertPrompt.h */,
316+ 912D1263134A162000721EE4 /* AlertPrompt.m */,
317 );
318 path = controls;
319 sourceTree = "<group>";
320@@ -389,12 +408,16 @@
321 93F334461247F9DE006C6707 /* SFHFKeychainUtils.m */,
322 93EE2AEE124993F100E7E060 /* ArtistListParser.h */,
323 93EE2AEF124993F100E7E060 /* ArtistListParser.m */,
324- 93EE2BA11249F33D00E7E060 /* AlbumListParser.h */,
325- 93EE2BA21249F33D00E7E060 /* AlbumListParser.m */,
326+ 9110DC42134EAC720046B8E4 /* AlbumListParser.h */,
327+ 9110DC43134EAC730046B8E4 /* AlbumListParser.m */,
328 912D1257134617F600721EE4 /* SongListParser.h */,
329 912D1258134617F600721EE4 /* SongListParser.m */,
330 9123D1C1132816D200B40210 /* PlaylistListParser.h */,
331 9123D1C2132816D200B40210 /* PlaylistListParser.m */,
332+ 93EE2BA11249F33D00E7E060 /* ArtistParser.h */,
333+ 93EE2BA21249F33D00E7E060 /* ArtistParser.m */,
334+ 9110DC36134C04590046B8E4 /* AlbumParser.h */,
335+ 9110DC37134C04590046B8E4 /* AlbumParser.m */,
336 91E88607132DA82000618994 /* PlaylistParser.h */,
337 91E88608132DA82000618994 /* PlaylistParser.m */,
338 93BC5207124C181600B7587C /* Subsonic.h */,
339@@ -451,6 +474,8 @@
340 912D392513311FC400A443B2 /* SongListViewController.m */,
341 9123D19F13257ADF00B40210 /* PlaylistListViewController.h */,
342 9123D1A013257ADF00B40210 /* PlaylistListViewController.m */,
343+ 912D1265134B609500721EE4 /* PlaylistEditViewController.h */,
344+ 912D1266134B609600721EE4 /* PlaylistEditViewController.m */,
345 93F3348D1247FCDC006C6707 /* ArtistViewController.h */,
346 93F3348E1247FCDC006C6707 /* ArtistViewController.m */,
347 93F3349B1247FCDC006C6707 /* AlbumViewController.h */,
348@@ -620,7 +645,7 @@
349 93F334A71247FCDC006C6707 /* SubsonicTableViewController.m in Sources */,
350 9354D0AB1248267B00733067 /* NSDictionary+Extras.m in Sources */,
351 93EE2AF0124993F100E7E060 /* ArtistListParser.m in Sources */,
352- 93EE2BA31249F33D00E7E060 /* AlbumListParser.m in Sources */,
353+ 93EE2BA31249F33D00E7E060 /* ArtistParser.m in Sources */,
354 93BC5209124C181600B7587C /* Subsonic.m in Sources */,
355 93BC52A7124C1E6900B7587C /* StreamingPlayer.m in Sources */,
356 93BC53FB124C7C8D00B7587C /* DataCache.m in Sources */,
357@@ -639,6 +664,11 @@
358 912D392613311FC600A443B2 /* SongListViewController.m in Sources */,
359 91B3A4441344CF92006C8193 /* SubsonicIndexedTableViewController.m in Sources */,
360 912D1259134617F600721EE4 /* SongListParser.m in Sources */,
361+ 912D1264134A162000721EE4 /* AlertPrompt.m in Sources */,
362+ 912D1267134B609700721EE4 /* PlaylistEditViewController.m in Sources */,
363+ 9110DC38134C045A0046B8E4 /* AlbumParser.m in Sources */,
364+ 9110DC41134E4EEF0046B8E4 /* NSMutableSet+Extras.m in Sources */,
365+ 9110DC44134EAC740046B8E4 /* AlbumListParser.m in Sources */,
366 );
367 runOnlyForDeploymentPostprocessing = 0;
368 };
369
370=== modified file 'musicstreaming/models/Album.m'
371--- musicstreaming/models/Album.m 2011-04-01 03:03:49 +0000
372+++ musicstreaming/models/Album.m 2011-04-08 19:49:28 +0000
373@@ -57,22 +57,20 @@
374
375 - (void)encodeWithCoder:(NSCoder*)encoder
376 {
377- [encoder encodeObject:title];
378- [encoder encodeObject:albumId];
379- [encoder encodeObject:coverArtId];
380+ [encoder encodeObject:title forKey:@"title"];
381+ [encoder encodeObject:albumId forKey:@"albumId"];
382+ [encoder encodeObject:coverArtId forKey:@"coverArtId"];
383 }
384
385-
386 - (id)initWithCoder:(NSCoder*)decoder
387 {
388- title = [[decoder decodeObject] retain];
389- albumId = [[decoder decodeObject] retain];
390- coverArtId = [[decoder decodeObject] retain];
391+ title = [[decoder decodeObjectForKey:@"title"] retain];
392+ albumId = [[decoder decodeObjectForKey:@"albumId"] retain];
393+ coverArtId = [[decoder decodeObjectForKey:@"coverArtId"] retain];
394
395 return self;
396 }
397
398-
399 - (void) dealloc
400 {
401 [title release];
402
403=== modified file 'musicstreaming/models/Playlist.h'
404--- musicstreaming/models/Playlist.h 2011-04-01 03:03:49 +0000
405+++ musicstreaming/models/Playlist.h 2011-04-08 19:49:28 +0000
406@@ -20,16 +20,16 @@
407 #import <Foundation/Foundation.h>
408
409
410-@interface Playlist : NSObject
411+@interface Playlist : NSObject <NSCoding>
412 {
413- NSString *playlistID;
414+ NSString *playlistId;
415 NSString *name;
416 NSMutableArray *contents;
417 }
418-@property(nonatomic,retain) NSString *playlistID;
419+@property(nonatomic,retain) NSString *playlistId;
420 @property(nonatomic,retain) NSString *name;
421 @property(nonatomic,retain) NSMutableArray *contents;
422-- (id)initWithDictionary:(NSDictionary*)dict;
423+- (id)initWithCoder:(NSCoder *)aDecoder;
424 - (BOOL)matchesSearchQuery:(NSString*)query;
425 @end
426
427
428=== modified file 'musicstreaming/models/Playlist.m'
429--- musicstreaming/models/Playlist.m 2011-04-01 03:03:49 +0000
430+++ musicstreaming/models/Playlist.m 2011-04-08 19:49:28 +0000
431@@ -21,22 +21,39 @@
432
433 @implementation Playlist
434
435-@synthesize playlistID, name, contents;
436+@synthesize playlistId, name, contents;
437
438-- (id)initWithDictionary:(NSDictionary*)dict
439+- (id)init
440 {
441 if ((self = [super init]))
442 {
443- self.playlistID = [dict objectForKey:@"id"];
444- self.name = [dict objectForKey:@"name"];
445+ self.playlistId = nil;
446+ self.name = nil;
447 self.contents = [NSMutableArray array];
448 }
449 return self;
450 }
451
452+- (void)encodeWithCoder:(NSCoder*)encoder
453+{
454+ [encoder encodeObject:playlistId forKey:@"playlistId"];
455+ [encoder encodeObject:name forKey:@"name"];
456+ [encoder encodeObject:contents forKey:@"contents"];
457+}
458+
459+
460+- (id)initWithCoder:(NSCoder*)decoder
461+{
462+ playlistId = [[decoder decodeObjectForKey:@"playlistId"] retain];
463+ name = [[decoder decodeObjectForKey:@"name"] retain];
464+ contents = [[decoder decodeObjectForKey:@"contents"] retain];
465+
466+ return self;
467+}
468+
469 - (void)dealloc
470 {
471- self.playlistID = NULL;
472+ self.playlistId = NULL;
473 self.name = NULL;
474 self.contents = NULL;
475
476
477=== modified file 'musicstreaming/models/Song.m'
478--- musicstreaming/models/Song.m 2011-04-01 03:03:49 +0000
479+++ musicstreaming/models/Song.m 2011-04-08 19:49:28 +0000
480@@ -67,36 +67,38 @@
481
482 - (void)encodeWithCoder:(NSCoder*)encoder
483 {
484- [encoder encodeObject: title];
485- [encoder encodeObject: songId];
486- [encoder encodeObject: artist];
487- [encoder encodeObject: album];
488- [encoder encodeObject: genre];
489- [encoder encodeObject: coverArtId];
490- [encoder encodeObject: path];
491- [encoder encodeObject: duration];
492- [encoder encodeObject: bitRate];
493- [encoder encodeObject: track];
494- [encoder encodeObject: year];
495- [encoder encodeObject: size];
496+ [encoder encodeObject:title forKey:@"title"];
497+ [encoder encodeObject:songId forKey:@"songId"];
498+ [encoder encodeObject:artist forKey:@"artist"];
499+ [encoder encodeObject:album forKey:@"album"];
500+ [encoder encodeObject:genre forKey:@"genre"];
501+ [encoder encodeObject:coverArtId forKey:@"coverArtId"];
502+ [encoder encodeObject:path forKey:@"path"];
503+ [encoder encodeObject:duration forKey:@"duration"];
504+ [encoder encodeObject:bitRate forKey:@"bitRate"];
505+ [encoder encodeObject:track forKey:@"track"];
506+ [encoder encodeObject:year forKey:@"year"];
507+ [encoder encodeObject:size forKey:@"size"];
508 }
509
510
511 -(id) initWithCoder: (NSCoder *) decoder
512 {
513- title = [[decoder decodeObject] retain];
514- songId = [[decoder decodeObject] retain];
515- artist = [[decoder decodeObject] retain];
516- album = [[decoder decodeObject] retain];
517- genre = [[decoder decodeObject] retain];
518- coverArtId = [[decoder decodeObject] retain];
519- path = [[decoder decodeObject] retain];
520- duration = [[decoder decodeObject] retain];
521- bitRate = [[decoder decodeObject] retain];
522- track = [[decoder decodeObject] retain];
523- year = [[decoder decodeObject] retain];
524- size = [[decoder decodeObject] retain];
525-
526+ if ((self = [super init]))
527+ {
528+ title = [[decoder decodeObjectForKey:@"title"] retain];
529+ songId = [[decoder decodeObjectForKey:@"songId"] retain];
530+ artist = [[decoder decodeObjectForKey:@"artist"] retain];
531+ album = [[decoder decodeObjectForKey:@"album"] retain];
532+ genre = [[decoder decodeObjectForKey:@"genre"] retain];
533+ coverArtId = [[decoder decodeObjectForKey:@"coverArtId"] retain];
534+ path = [[decoder decodeObjectForKey:@"path"] retain];
535+ duration = [[decoder decodeObjectForKey:@"duration"] retain];
536+ bitRate = [[decoder decodeObjectForKey:@"bitRate"] retain];
537+ track = [[decoder decodeObjectForKey:@"track"] retain];
538+ year = [[decoder decodeObjectForKey:@"year"] retain];
539+ size = [[decoder decodeObjectForKey:@"size"] retain];
540+ }
541 return self;
542 }
543
544
545=== added file 'musicstreaming/utilities/AlbumListParser.h'
546--- musicstreaming/utilities/AlbumListParser.h 1970-01-01 00:00:00 +0000
547+++ musicstreaming/utilities/AlbumListParser.h 2011-04-08 19:49:28 +0000
548@@ -0,0 +1,37 @@
549+//
550+// AlbumListParser.h
551+// iSub
552+//
553+// Created by Zachery Bir on 4/7/11.
554+// Copyright 2011 Canonical Ltd.
555+//
556+// This program is free software: you can redistribute it and/or modify it
557+// under the terms of the GNU Affero General Public License version 3,
558+// as published by the Free Software Foundation.
559+//
560+// This program is distributed in the hope that it will be useful, but
561+// WITHOUT ANY WARRANTY; without even the implied warranties of
562+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
563+// PURPOSE. See the GNU Affero General Public License for more details.
564+//
565+// You should have received a copy of the GNU Affero General Public License
566+// along with this program. If not, see <http://www.gnu.org/licenses/>.
567+
568+#import <Foundation/Foundation.h>
569+
570+@class Album;
571+
572+@interface AlbumListParser : NSObject <NSXMLParserDelegate>
573+{
574+ NSMutableArray *albums;
575+ NSMutableArray *indexes;
576+ Album *album;
577+ NSString *index;
578+ NSMutableDictionary *groupedAlbums;
579+}
580+@property(nonatomic,retain) NSMutableDictionary *groupedAlbums;
581+@property(nonatomic,retain) NSMutableArray *albums;
582+@property(nonatomic,retain) NSMutableArray *indexes;
583+@property(nonatomic,retain) Album *album;
584+@property(nonatomic,retain) NSString *index;
585+@end
586
587=== added file 'musicstreaming/utilities/AlbumListParser.m'
588--- musicstreaming/utilities/AlbumListParser.m 1970-01-01 00:00:00 +0000
589+++ musicstreaming/utilities/AlbumListParser.m 2011-04-08 19:49:28 +0000
590@@ -0,0 +1,98 @@
591+//
592+// AlbumListParser.m
593+// iSub
594+//
595+// Created by Zachery Bir on 4/7/11.
596+// Copyright 2011 Canonical Ltd.
597+//
598+// This program is free software: you can redistribute it and/or modify it
599+// under the terms of the GNU Affero General Public License version 3,
600+// as published by the Free Software Foundation.
601+//
602+// This program is distributed in the hope that it will be useful, but
603+// WITHOUT ANY WARRANTY; without even the implied warranties of
604+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
605+// PURPOSE. See the GNU Affero General Public License for more details.
606+//
607+// You should have received a copy of the GNU Affero General Public License
608+// along with this program. If not, see <http://www.gnu.org/licenses/>.
609+
610+#import "AlbumListParser.h"
611+#import "Album.h"
612+
613+@implementation AlbumListParser
614+
615+@synthesize albums, indexes, groupedAlbums;
616+@synthesize album, index;
617+
618+- (id)init
619+{
620+ if ((self = [super init]))
621+ {
622+ albums = [[NSMutableArray alloc] init];
623+ indexes = [[NSMutableArray alloc] init];
624+ groupedAlbums = [[NSMutableDictionary alloc] init];
625+ self.album = NULL;
626+ self.index = NULL;
627+ }
628+ return self;
629+}
630+
631+
632+- (void) subsonicErrorCode:(NSString *)errorCode message:(NSString *)message
633+{
634+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"Dismiss", @"") otherButtonTitles:nil];
635+ [alert show];
636+ [alert release];
637+}
638+
639+
640+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
641+{
642+ if ([elementName isEqualToString:@"error"])
643+ {
644+ [self subsonicErrorCode:[attributeDict objectForKey:@"code"] message:[attributeDict objectForKey:@"message"]];
645+ }
646+ else if ([elementName isEqualToString:@"index"]) //letters that appear on the right side of the table.
647+ {
648+ self.index = [attributeDict objectForKey:@"name"];
649+ [indexes addObject:self.index];
650+ [groupedAlbums setObject:[NSMutableArray array] forKey:self.index];
651+ }
652+ else if ([elementName isEqualToString:@"album"])
653+ {
654+ self.album = [[[Album alloc] init] autorelease];
655+ self.album.title = [attributeDict objectForKey:@"title"];
656+ self.album.albumId = [attributeDict objectForKey:@"id"];
657+
658+ [albums addObject:self.album];
659+ NSMutableArray *group = [groupedAlbums objectForKey:self.index];
660+ [group addObject:self.album];
661+ }
662+}
663+
664+
665+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
666+{
667+ if ([elementName isEqualToString:@"album"])
668+ {
669+ self.album = NULL;
670+ }
671+ else if ([elementName isEqualToString:@"index"])
672+ {
673+ self.index = NULL;
674+ }
675+}
676+
677+
678+- (void) dealloc
679+{
680+ self.album = NULL;
681+ self.index = NULL;
682+ RELEASE_SAFELY(groupedAlbums);
683+ RELEASE_SAFELY(albums);
684+ RELEASE_SAFELY(indexes);
685+ [super dealloc];
686+}
687+
688+@end
689\ No newline at end of file
690
691=== added file 'musicstreaming/utilities/AlbumParser.h'
692--- musicstreaming/utilities/AlbumParser.h 1970-01-01 00:00:00 +0000
693+++ musicstreaming/utilities/AlbumParser.h 2011-04-08 19:49:28 +0000
694@@ -0,0 +1,27 @@
695+//
696+// AlbumParser.h
697+// iSub
698+//
699+// Created by Zachery Bir on 4/5/11.
700+// Copyright 2011 Canonical. All rights reserved.
701+//
702+// This program is free software: you can redistribute it and/or modify it
703+// under the terms of the GNU Affero General Public License version 3,
704+// as published by the Free Software Foundation.
705+//
706+// This program is distributed in the hope that it will be useful, but
707+// WITHOUT ANY WARRANTY; without even the implied warranties of
708+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
709+// PURPOSE. See the GNU Affero General Public License for more details.
710+//
711+// You should have received a copy of the GNU Affero General Public License
712+// along with this program. If not, see <http://www.gnu.org/licenses/>.
713+
714+#import <Foundation/Foundation.h>
715+
716+@interface AlbumParser : NSObject <NSXMLParserDelegate>
717+{
718+ NSMutableArray *songs;
719+}
720+@property(nonatomic,retain) NSMutableArray *songs;
721+@end
722
723=== added file 'musicstreaming/utilities/AlbumParser.m'
724--- musicstreaming/utilities/AlbumParser.m 1970-01-01 00:00:00 +0000
725+++ musicstreaming/utilities/AlbumParser.m 2011-04-08 19:49:28 +0000
726@@ -0,0 +1,64 @@
727+//
728+// AlbumParser.m
729+// iSub
730+//
731+// Created by Zachery Bir on 4/5/11.
732+// Copyright 2011 Canonical. All rights reserved.
733+//
734+// This program is free software: you can redistribute it and/or modify it
735+// under the terms of the GNU Affero General Public License version 3,
736+// as published by the Free Software Foundation.
737+//
738+// This program is distributed in the hope that it will be useful, but
739+// WITHOUT ANY WARRANTY; without even the implied warranties of
740+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
741+// PURPOSE. See the GNU Affero General Public License for more details.
742+//
743+// You should have received a copy of the GNU Affero General Public License
744+// along with this program. If not, see <http://www.gnu.org/licenses/>.
745+
746+#import "AlbumParser.h"
747+#import "Album.h"
748+#import "Song.h"
749+
750+@implementation AlbumParser
751+
752+@synthesize songs;
753+
754+- (id)init
755+{
756+ if ((self = [super init]))
757+ {
758+ songs = [[NSMutableArray alloc] init];
759+ }
760+ return self;
761+}
762+
763+- (void) subsonicErrorCode:(NSString *)errorCode message:(NSString *)message
764+{
765+ UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Error" message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"Dismiss", @"") otherButtonTitles:nil];
766+ [alert show];
767+ [alert release];
768+}
769+
770+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
771+{
772+ if ([elementName isEqualToString:@"error"])
773+ {
774+ [self subsonicErrorCode:[attributeDict objectForKey:@"code"] message:[attributeDict objectForKey:@"message"]];
775+ }
776+ else if ([elementName isEqualToString:@"child"])
777+ {
778+ Song *song = [[Song alloc] initWithDictionary:attributeDict];
779+ [self.songs addObject:song];
780+ [song release];
781+ }
782+}
783+
784+- (void)dealloc
785+{
786+ [songs release];
787+ [super dealloc];
788+}
789+
790+@end
791
792=== modified file 'musicstreaming/utilities/ArtistListParser.h'
793--- musicstreaming/utilities/ArtistListParser.h 2011-03-29 14:22:42 +0000
794+++ musicstreaming/utilities/ArtistListParser.h 2011-04-08 19:49:28 +0000
795@@ -30,8 +30,8 @@
796 NSMutableDictionary *groupedArtists;
797 }
798 @property(nonatomic,retain) NSMutableDictionary *groupedArtists;
799-@property(nonatomic,retain) NSArray *artists;
800-@property(nonatomic,retain) NSArray *indexes;
801+@property(nonatomic,retain) NSMutableArray *artists;
802+@property(nonatomic,retain) NSMutableArray *indexes;
803 @property(nonatomic,retain) Artist *artist;
804 @property(nonatomic,retain) NSString *index;
805 @end
806
807=== renamed file 'musicstreaming/utilities/AlbumListParser.h' => 'musicstreaming/utilities/ArtistParser.h'
808--- musicstreaming/utilities/AlbumListParser.h 2011-03-29 14:22:42 +0000
809+++ musicstreaming/utilities/ArtistParser.h 2011-04-08 19:49:28 +0000
810@@ -1,5 +1,5 @@
811 //
812-// AlbumListParser.h
813+// ArtistParser.h
814 // iSub
815 //
816 // Created by Aaron Brethorst on 9/22/10.
817@@ -19,7 +19,7 @@
818
819 #import <Foundation/Foundation.h>
820
821-@interface AlbumListParser : NSObject <NSXMLParserDelegate>
822+@interface ArtistParser : NSObject <NSXMLParserDelegate>
823 {
824 NSMutableArray *albums;
825 NSMutableArray *songs;
826
827=== renamed file 'musicstreaming/utilities/AlbumListParser.m' => 'musicstreaming/utilities/ArtistParser.m'
828--- musicstreaming/utilities/AlbumListParser.m 2011-04-01 14:55:49 +0000
829+++ musicstreaming/utilities/ArtistParser.m 2011-04-08 19:49:28 +0000
830@@ -1,5 +1,5 @@
831 //
832-// AlbumListParser.m
833+// ArtistParser.m
834 // iSub
835 //
836 // Created by Aaron Brethorst on 9/22/10.
837@@ -17,11 +17,11 @@
838 // You should have received a copy of the GNU Affero General Public License
839 // along with this program. If not, see <http://www.gnu.org/licenses/>.
840
841-#import "AlbumListParser.h"
842+#import "ArtistParser.h"
843 #import "Album.h"
844 #import "Song.h"
845
846-@implementation AlbumListParser
847+@implementation ArtistParser
848
849 @synthesize albums, songs;
850
851
852=== modified file 'musicstreaming/utilities/PlaylistListParser.h'
853--- musicstreaming/utilities/PlaylistListParser.h 2011-03-29 14:22:42 +0000
854+++ musicstreaming/utilities/PlaylistListParser.h 2011-04-08 19:49:28 +0000
855@@ -23,5 +23,5 @@
856 {
857 NSMutableArray *names;
858 }
859-@property(nonatomic,retain) NSArray *names;
860+@property(nonatomic,retain) NSMutableArray *names;
861 @end
862
863=== modified file 'musicstreaming/utilities/PlaylistListParser.m'
864--- musicstreaming/utilities/PlaylistListParser.m 2011-03-29 14:22:42 +0000
865+++ musicstreaming/utilities/PlaylistListParser.m 2011-04-08 19:49:28 +0000
866@@ -51,7 +51,7 @@
867 {
868 Playlist *playlist = [[[Playlist alloc] init] autorelease];
869 playlist.name = [attributeDict objectForKey:@"name"];
870- playlist.playlistID = [attributeDict objectForKey:@"id"];
871+ playlist.playlistId = [attributeDict objectForKey:@"id"];
872
873 if (![playlist.name isEqual:@".AppleDouble"])
874 {
875
876=== modified file 'musicstreaming/utilities/PlaylistParser.h'
877--- musicstreaming/utilities/PlaylistParser.h 2011-03-29 14:22:42 +0000
878+++ musicstreaming/utilities/PlaylistParser.h 2011-04-08 19:49:28 +0000
879@@ -19,13 +19,13 @@
880
881 #import <Foundation/Foundation.h>
882
883-@class Playlist;
884-
885 @interface PlaylistParser : NSObject <NSXMLParserDelegate>
886 {
887- Playlist *playlist;
888- NSMutableArray *songs;
889+ NSString *playlistId;
890+ NSString *name;
891+ NSMutableArray *contents;
892 }
893-@property(nonatomic,retain) Playlist *playlist;
894-@property(nonatomic,retain) NSMutableArray *songs;
895+@property(nonatomic,retain) NSString *playlistId;
896+@property(nonatomic,retain) NSString *name;
897+@property(nonatomic,retain) NSMutableArray *contents;
898 @end
899
900=== modified file 'musicstreaming/utilities/PlaylistParser.m'
901--- musicstreaming/utilities/PlaylistParser.m 2011-03-29 14:22:42 +0000
902+++ musicstreaming/utilities/PlaylistParser.m 2011-04-08 19:49:28 +0000
903@@ -18,19 +18,19 @@
904 // along with this program. If not, see <http://www.gnu.org/licenses/>.
905
906 #import "PlaylistParser.h"
907-#import "Playlist.h"
908 #import "Song.h"
909
910
911 @implementation PlaylistParser
912-@synthesize playlist, songs;
913+@synthesize playlistId, name, contents;
914
915 - (id)init
916 {
917 if ((self = [super init]))
918 {
919- playlist = [[Playlist alloc] init];
920- songs = [[NSMutableArray alloc] init];
921+ playlistId = nil;
922+ name = nil;
923+ contents = [[NSMutableArray alloc] init];
924 }
925 return self;
926 }
927@@ -53,14 +53,14 @@
928 {
929 if (![[attributeDict objectForKey:@"name"] isEqual:@".AppleDouble"])
930 {
931- playlist.name = [attributeDict objectForKey:@"name"];
932- playlist.playlistID = [attributeDict objectForKey:@"id"];
933+ self.playlistId = [attributeDict objectForKey:@"id"];
934+ self.name = [attributeDict objectForKey:@"name"];
935 }
936 }
937 else if ([elementName isEqualToString:@"entry"])
938 {
939 Song *song = [[Song alloc] initWithDictionary:attributeDict];
940- [songs addObject:song];
941+ [contents addObject:song];
942 [song release];
943 }
944 }
945@@ -68,8 +68,9 @@
946
947 - (void) dealloc
948 {
949- RELEASE_SAFELY(playlist);
950- RELEASE_SAFELY(songs)
951+ playlistId = NULL;
952+ name = NULL;
953+ RELEASE_SAFELY(contents);
954 [super dealloc];
955 }
956
957
958=== modified file 'musicstreaming/utilities/SongListParser.h'
959--- musicstreaming/utilities/SongListParser.h 2011-04-01 14:55:49 +0000
960+++ musicstreaming/utilities/SongListParser.h 2011-04-08 19:49:28 +0000
961@@ -30,8 +30,8 @@
962 NSMutableDictionary *groupedSongs;
963 }
964 @property(nonatomic,retain) NSMutableDictionary *groupedSongs;
965-@property(nonatomic,retain) NSArray *songs;
966-@property(nonatomic,retain) NSArray *indexes;
967+@property(nonatomic,retain) NSMutableArray *songs;
968+@property(nonatomic,retain) NSMutableArray *indexes;
969 @property(nonatomic,retain) NSString *index;
970 @property(nonatomic,retain) Song *song;
971 @end
972
973=== modified file 'musicstreaming/utilities/StreamingPlayer.m'
974--- musicstreaming/utilities/StreamingPlayer.m 2011-03-29 14:22:42 +0000
975+++ musicstreaming/utilities/StreamingPlayer.m 2011-04-08 19:49:28 +0000
976@@ -92,7 +92,7 @@
977 self.seekTime = [[defaults objectForKey:@"seekTime"] floatValue];
978 self.isPlaying = YES;
979
980- self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongID:self.currentSong.songId];
981+ self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongId:self.currentSong.songId];
982 [self createStreamer];
983 [self.streamer seekToTime:self.seekTime];
984 }
985@@ -236,7 +236,7 @@
986 #endif
987 self.currentSong = [playlist objectAtIndex:index];
988
989- self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongID:self.currentSong.songId];
990+ self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongId:self.currentSong.songId];
991
992 [self.streamer stop];
993 [self playPauseSong];
994@@ -286,7 +286,7 @@
995
996 currentSong = [playlist objectAtIndex:0];
997
998- self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongID:self.currentSong.songId];
999+ self.songUrl = [[Subsonic sharedSubsonic] getStreamingURLForSongId:self.currentSong.songId];
1000
1001 [self.streamer stop];
1002 [self playPauseSong];
1003
1004=== modified file 'musicstreaming/utilities/Subsonic.h'
1005--- musicstreaming/utilities/Subsonic.h 2011-03-29 14:22:42 +0000
1006+++ musicstreaming/utilities/Subsonic.h 2011-04-08 19:49:28 +0000
1007@@ -36,8 +36,8 @@
1008 @property(nonatomic,assign) NSInteger cachedIPHour;
1009 + (Subsonic *)sharedSubsonic;
1010 - (NSURL *)getBaseUrl:(NSString *)action;
1011-- (NSURL *)getBaseUrl:(NSString *)action parameters:(NSDictionary*)extraParameters;
1012-- (NSURL *)getStreamingURLForSongID:(NSString*)songID;
1013+- (NSURL *)getBaseUrl:(NSString *)action parameters:(NSSet*)extraParameters;
1014+- (NSURL *)getStreamingURLForSongId:(NSString*)songId;
1015 - (BOOL)canPingServer;
1016 - (BOOL)isURLValid:(NSString *)url;
1017 - (void)removeCredentials;
1018
1019=== modified file 'musicstreaming/utilities/Subsonic.m'
1020--- musicstreaming/utilities/Subsonic.m 2011-04-01 22:35:01 +0000
1021+++ musicstreaming/utilities/Subsonic.m 2011-04-08 19:49:28 +0000
1022@@ -22,7 +22,7 @@
1023 #include <netinet/in.h>
1024 #include <netdb.h>
1025 #include <arpa/inet.h>
1026-#import "NSDictionary+Extras.h"
1027+#import "NSMutableSet+Extras.h"
1028
1029 @implementation Subsonic
1030 @synthesize defaultURL, defaultUserName, defaultPassword, cachedIP, cachedIPHour;
1031@@ -98,9 +98,11 @@
1032 self.defaultPassword = password;
1033 }
1034
1035-- (NSURL *)getStreamingURLForSongID:(NSString*)songID
1036+- (NSURL *)getStreamingURLForSongId:(NSString*)songId
1037 {
1038- return [self getBaseUrl:@"stream.view" parameters:[NSDictionary dictionaryWithObject:songID forKey:@"id"]];
1039+ NSMutableSet *parameters = [NSMutableSet set];
1040+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", songId, nil]];
1041+ return [self getBaseUrl:@"stream.view" parameters:parameters];
1042 }
1043
1044 - (NSURL *)getBaseUrl:(NSString *)action
1045@@ -108,17 +110,17 @@
1046 return [self getBaseUrl:action parameters:nil];
1047 }
1048
1049-- (NSURL *)getBaseUrl:(NSString *)action parameters:(NSDictionary*)extraParameters
1050+- (NSURL *)getBaseUrl:(NSString *)action parameters:(NSSet*)extraParameters
1051 {
1052 if (self.defaultUserName && self.defaultPassword)
1053 {
1054- NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:extraParameters];
1055-
1056- [params setObject:self.defaultUserName forKey:@"u"];
1057- [params setObject:self.defaultPassword forKey:@"p"];
1058- [params setObject:@"1.1.0" forKey:@"v"];
1059- [params setObject:@"iSub" forKey:@"c"];
1060-
1061+ NSMutableSet *params = [NSMutableSet setWithSet:extraParameters];
1062+
1063+ [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"u", self.defaultUserName, nil]];
1064+ [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"p", self.defaultPassword, nil]];
1065+ [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"v", @"1.1.0", nil]];
1066+ [params addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"c", @"iSub", nil]];
1067+
1068 return [NSURL URLWithString:[NSString stringWithFormat:@"%@/rest/%@?%@", self.defaultURL, action, [params urlEncodedString]]];
1069 }
1070 else
1071
1072=== modified file 'musicstreaming/view_controllers/AlbumListViewController.m'
1073--- musicstreaming/view_controllers/AlbumListViewController.m 2011-04-01 03:07:07 +0000
1074+++ musicstreaming/view_controllers/AlbumListViewController.m 2011-04-08 19:49:28 +0000
1075@@ -18,16 +18,140 @@
1076 // along with this program. If not, see <http://www.gnu.org/licenses/>.
1077
1078 #import "AlbumListViewController.h"
1079+#import "DataCache.h"
1080+#import "AlbumListParser.h"
1081+#import "AlbumUITableViewCell.h"
1082+#import "Album.h"
1083+#import "AlbumViewController.h"
1084
1085 @implementation AlbumListViewController
1086
1087+#pragma mark - View stuff
1088+
1089+- (void)viewDidLoad
1090+{
1091+ [super viewDidLoad];
1092+ self.tableView.rowHeight = 60.0f;
1093+
1094+ [self loadData:NO];
1095+}
1096+
1097 #pragma mark - Data Loading
1098
1099 - (void)beginLoadingData:(NSString*)force
1100 {
1101+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1102+
1103+ NSDictionary *cachedAlbums = [[DataCache sharedDataCache] objectForKey:@"AlbumsList"];
1104+
1105+ if (cachedAlbums && ![force isEqual:@"YES"])
1106+ {
1107+ self.tableData = [cachedAlbums objectForKey:@"albums"];
1108+ self.indexes = [cachedAlbums objectForKey:@"indexes"];
1109+ self.groupedTableData = [cachedAlbums objectForKey:@"groupedAlbums"];
1110+ }
1111+ else
1112+ {
1113+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getAllAlbums.view"];
1114+ NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
1115+
1116+ AlbumListParser *parser = [[AlbumListParser alloc] init];
1117+ [xmlParser setDelegate:parser];
1118+
1119+ if (![xmlParser parse])
1120+ {
1121+ [self performSelectorOnMainThread:@selector(failedLoadingData:) withObject:[xmlParser parserError] waitUntilDone:NO];
1122+ [xmlParser release];
1123+ [parser release];
1124+ [pool release];
1125+ return;
1126+ }
1127+
1128+ self.tableData = parser.albums;
1129+ if ([self.tableData count] <= 8)
1130+ {
1131+ indexed = NO;
1132+ }
1133+ self.indexes = parser.indexes;
1134+ self.groupedTableData = parser.groupedAlbums;
1135+
1136+ [xmlParser release];
1137+ [parser release];
1138+
1139+ NSDictionary *cacheData = [NSDictionary dictionaryWithObjectsAndKeys:self.tableData, @"albums",
1140+ self.indexes, @"indexes", self.groupedTableData, @"groupedAlbums", nil];
1141+
1142+ [[DataCache sharedDataCache] setObject:cacheData forKey:@"AlbumsList"];
1143+ }
1144+
1145 [self performSelectorOnMainThread:@selector(finishLoadingData) withObject:nil waitUntilDone:NO];
1146+ [pool release];
1147 }
1148
1149 #pragma mark - UITableView
1150
1151+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
1152+{
1153+ static NSString *AlbumCellIdentifier = @"AlbumCellIdentifier";
1154+ AlbumUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:AlbumCellIdentifier];
1155+
1156+ if (nil == cell)
1157+ {
1158+ cell = [[[AlbumUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AlbumCellIdentifier] autorelease];
1159+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1160+ }
1161+
1162+ Album *a = nil;
1163+
1164+ if (self.searchDisplayController.searchResultsTableView == tableView)
1165+ {
1166+ a = [self.searchResults objectAtIndex:indexPath.row];
1167+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1168+ }
1169+ else
1170+ {
1171+ cell.accessoryType = UITableViewCellAccessoryNone;
1172+
1173+ if (indexed)
1174+ {
1175+ NSString *index = [self.indexes objectAtIndex:indexPath.section];
1176+ a = [[self.groupedTableData objectForKey:index] objectAtIndex:indexPath.row];
1177+ }
1178+ else
1179+ {
1180+ a = [self.tableData objectAtIndex:indexPath.row];
1181+ }
1182+ }
1183+
1184+ cell.albumNameLabel.text = a.title;
1185+ [self loadCoverArtForAlbum:a intoImageView:cell.coverArtView withSize:120];
1186+
1187+ return cell;
1188+}
1189+
1190+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
1191+{
1192+ Album *selection = nil;
1193+
1194+ if (self.searchDisplayController.searchResultsTableView == tableView)
1195+ {
1196+ selection = [self.searchResults objectAtIndex:indexPath.row];
1197+ }
1198+ else if(indexed)
1199+ {
1200+ NSString *index = [self.indexes objectAtIndex:indexPath.section];
1201+ selection = [[self.groupedTableData objectForKey:index] objectAtIndex:indexPath.row];
1202+ }
1203+ else
1204+ {
1205+ selection = [self.tableData objectAtIndex:indexPath.row];
1206+ }
1207+
1208+ AlbumViewController *albumViewController = [[AlbumViewController alloc] initWithStyle:UITableViewStylePlain];
1209+ albumViewController.album = selection;
1210+ // albumViewController.artist = @"AYFKMWTS?"; // TODO: Make server-side views that give back enough info
1211+ [self.navigationController pushViewController:albumViewController animated:YES];
1212+ [albumViewController release];
1213+}
1214+
1215 @end
1216
1217=== modified file 'musicstreaming/view_controllers/AlbumViewController.h'
1218--- musicstreaming/view_controllers/AlbumViewController.h 2011-03-29 14:22:42 +0000
1219+++ musicstreaming/view_controllers/AlbumViewController.h 2011-04-08 19:49:28 +0000
1220@@ -25,7 +25,7 @@
1221 @interface AlbumViewController : SubsonicTableViewController
1222 {
1223 UIView *headerView;
1224- Artist *artist;
1225+ NSString *artist;
1226 Album *album;
1227 AsynchronousImageViewCached* coverArt;
1228 UILabel *artistLabel;
1229@@ -33,6 +33,6 @@
1230 NSArray *songs;
1231 }
1232 @property(nonatomic,retain) NSArray *songs;
1233-@property(nonatomic,retain) Artist *artist;
1234+@property(nonatomic,retain) NSString *artist;
1235 @property(nonatomic,retain) Album *album;
1236 @end
1237
1238=== modified file 'musicstreaming/view_controllers/AlbumViewController.m'
1239--- musicstreaming/view_controllers/AlbumViewController.m 2011-03-29 14:22:42 +0000
1240+++ musicstreaming/view_controllers/AlbumViewController.m 2011-04-08 19:49:28 +0000
1241@@ -21,14 +21,14 @@
1242
1243 #import "AlbumUITableViewCell.h"
1244 #import "AsynchronousImageViewCached.h"
1245-#import "AlbumListParser.h"
1246-#import "Artist.h"
1247+#import "AlbumParser.h"
1248 #import "Album.h"
1249 #import "Song.h"
1250 #import "SongUITableViewCell.h"
1251 #import "NSDate+Extras.h"
1252 #import "StreamingPlayer.h"
1253 #import "DataCache.h"
1254+#import "NSMutableSet+Extras.h"
1255
1256 @interface AlbumViewController (Private)
1257 - (void)setupHeaderAndFooter;
1258@@ -80,10 +80,12 @@
1259 }
1260 else
1261 {
1262- NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getMusicDirectory.view" parameters:[NSDictionary dictionaryWithObject:self.album.albumId forKey:@"id"]];
1263+ NSMutableSet *parameters = [NSMutableSet set];
1264+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.album.albumId, nil]];
1265+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getMusicDirectory.view" parameters:parameters];
1266 NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
1267
1268- AlbumListParser *parser = [[AlbumListParser alloc] init];
1269+ AlbumParser *parser = [[AlbumParser alloc] init];
1270 [xmlParser setDelegate:parser];
1271
1272 if (![xmlParser parse])
1273@@ -232,7 +234,7 @@
1274 artistLabel.shadowOffset = CGSizeMake(0, 1);
1275 [headerView addSubview:artistLabel];
1276
1277- artistLabel.text = self.artist.name;
1278+ artistLabel.text = self.artist;
1279
1280 albumLabel = [[UILabel alloc] initWithFrame:CGRectMake(120, 30, 200, 20)];
1281 albumLabel.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
1282
1283=== modified file 'musicstreaming/view_controllers/ArtistListViewController.m'
1284--- musicstreaming/view_controllers/ArtistListViewController.m 2011-04-01 03:07:07 +0000
1285+++ musicstreaming/view_controllers/ArtistListViewController.m 2011-04-08 19:49:28 +0000
1286@@ -103,7 +103,7 @@
1287
1288 if (self.searchDisplayController.searchResultsTableView == tableView)
1289 {
1290- Artist *a = [searchResults objectAtIndex:indexPath.row];
1291+ Artist *a = [self.searchResults objectAtIndex:indexPath.row];
1292 cell.textLabel.text = a.name;
1293 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1294 }
1295@@ -134,7 +134,7 @@
1296
1297 if (self.searchDisplayController.searchResultsTableView == tableView)
1298 {
1299- selection = [searchResults objectAtIndex:indexPath.row];
1300+ selection = [self.searchResults objectAtIndex:indexPath.row];
1301 }
1302 else if(indexed)
1303 {
1304
1305=== modified file 'musicstreaming/view_controllers/ArtistViewController.m'
1306--- musicstreaming/view_controllers/ArtistViewController.m 2011-03-28 17:52:06 +0000
1307+++ musicstreaming/view_controllers/ArtistViewController.m 2011-04-08 19:49:28 +0000
1308@@ -32,11 +32,12 @@
1309 #import "AlbumViewController.h"
1310 #import "AlbumUITableViewCell.h"
1311 #import "AsynchronousImageViewCached.h"
1312-#import "AlbumListParser.h"
1313+#import "ArtistParser.h"
1314 #import "Artist.h"
1315 #import "Album.h"
1316 #import "Song.h"
1317 #import "DataCache.h"
1318+#import "NSMutableSet+Extras.h"
1319
1320 @implementation ArtistViewController
1321 @synthesize artist, albums, songs;
1322@@ -61,16 +62,6 @@
1323 [self loadData:NO];
1324 }
1325
1326-- (void)viewDidAppear:(BOOL)animated
1327-{
1328- [super viewDidAppear:animated];
1329-}
1330-
1331-- (void)viewWillDisappear:(BOOL)animated
1332-{
1333- [super viewWillDisappear:animated];
1334-}
1335-
1336 #pragma mark -
1337 #pragma mark Data Loader
1338
1339@@ -93,9 +84,11 @@
1340 }
1341 else
1342 {
1343- NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getMusicDirectory.view" parameters:[NSDictionary dictionaryWithObject:self.artist.artistId forKey:@"id"]];
1344+ NSMutableSet *parameters = [NSMutableSet set];
1345+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.artist.artistId, nil]];
1346+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getMusicDirectory.view" parameters:parameters];
1347 NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
1348- AlbumListParser *parser = [[AlbumListParser alloc] init];
1349+ ArtistParser *parser = [[ArtistParser alloc] init];
1350 [xmlParser setDelegate:parser];
1351
1352 if (![xmlParser parse])
1353@@ -155,10 +148,10 @@
1354 }
1355 }
1356
1357-- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
1358+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
1359 {
1360 static NSString *AlbumCellIdentifier = @"AlbumCellIdentifier";
1361- AlbumUITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:AlbumCellIdentifier];
1362+ AlbumUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:AlbumCellIdentifier];
1363
1364 if (nil == cell)
1365 {
1366@@ -187,10 +180,10 @@
1367 {
1368 Album *selection = [self.albums objectAtIndex:indexPath.row];
1369
1370- AlbumViewController *songsVC = [[[AlbumViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
1371- songsVC.album = selection;
1372- songsVC.artist = self.artist;
1373- [self.navigationController pushViewController:songsVC animated:YES];
1374+ AlbumViewController *albumViewController = [[[AlbumViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
1375+ albumViewController.album = selection;
1376+ albumViewController.artist = self.artist.name;
1377+ [self.navigationController pushViewController:albumViewController animated:YES];
1378 }
1379 else
1380 {
1381
1382=== added file 'musicstreaming/view_controllers/PlaylistEditViewController.h'
1383--- musicstreaming/view_controllers/PlaylistEditViewController.h 1970-01-01 00:00:00 +0000
1384+++ musicstreaming/view_controllers/PlaylistEditViewController.h 2011-04-08 19:49:28 +0000
1385@@ -0,0 +1,36 @@
1386+//
1387+// PlaylistEditViewController.h
1388+// iSub
1389+//
1390+// Created by Zachery Bir on 4/5/11.
1391+// Copyright 2011 Canonical Ltd.
1392+//
1393+// This program is free software: you can redistribute it and/or modify it
1394+// under the terms of the GNU Affero General Public License version 3,
1395+// as published by the Free Software Foundation.
1396+//
1397+// This program is distributed in the hope that it will be useful, but
1398+// WITHOUT ANY WARRANTY; without even the implied warranties of
1399+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1400+// PURPOSE. See the GNU Affero General Public License for more details.
1401+//
1402+// You should have received a copy of the GNU Affero General Public License
1403+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1404+
1405+#import "SubsonicIndexedTableViewController.h"
1406+
1407+@class Playlist;
1408+@class PlaylistListViewController;
1409+
1410+@interface PlaylistEditViewController : SubsonicIndexedTableViewController
1411+{
1412+ Playlist *playlist;
1413+ PlaylistListViewController *playlistListViewController;
1414+}
1415++ (UINavigationController *)navigableViewControllerWithPlaylist:(Playlist *)playlist originator:(PlaylistListViewController *)originator;
1416+- (id)initWithPlaylist:(Playlist *)aPlaylist;
1417+- (void)cancel:(id)sender;
1418+- (void)save:(id)sender;
1419+@property(nonatomic,retain) Playlist *playlist;
1420+@property(nonatomic,retain) PlaylistListViewController *playlistListViewController;
1421+@end
1422
1423=== added file 'musicstreaming/view_controllers/PlaylistEditViewController.m'
1424--- musicstreaming/view_controllers/PlaylistEditViewController.m 1970-01-01 00:00:00 +0000
1425+++ musicstreaming/view_controllers/PlaylistEditViewController.m 2011-04-08 19:49:28 +0000
1426@@ -0,0 +1,214 @@
1427+//
1428+// PlaylistEditViewController.m
1429+// iSub
1430+//
1431+// Created by Zachery Bir on 4/5/11.
1432+// Copyright 2011 Canonical Ltd.
1433+//
1434+// This program is free software: you can redistribute it and/or modify it
1435+// under the terms of the GNU Affero General Public License version 3,
1436+// as published by the Free Software Foundation.
1437+//
1438+// This program is distributed in the hope that it will be useful, but
1439+// WITHOUT ANY WARRANTY; without even the implied warranties of
1440+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1441+// PURPOSE. See the GNU Affero General Public License for more details.
1442+//
1443+// You should have received a copy of the GNU Affero General Public License
1444+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1445+
1446+#import "PlaylistEditViewController.h"
1447+#import "PlaylistListViewController.h"
1448+#import "Playlist.h"
1449+#import "Song.h"
1450+#import "DataCache.h"
1451+#import "SongListParser.h"
1452+#import "NSMutableSet+Extras.h"
1453+
1454+@implementation PlaylistEditViewController
1455+@synthesize playlist, playlistListViewController;
1456+
1457++ (UINavigationController *)navigableViewControllerWithPlaylist:(Playlist *)playlist originator:(PlaylistListViewController *)originator
1458+{
1459+ PlaylistEditViewController *playlistEditViewController = [[[PlaylistEditViewController alloc] initWithPlaylist:playlist] autorelease];
1460+ playlistEditViewController.playlistListViewController = originator;
1461+ UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:playlistEditViewController] autorelease];
1462+ return nav;
1463+}
1464+
1465+- (id)initWithPlaylist:(Playlist *)aPlaylist
1466+{
1467+ if ((self = [super initWithTitle:aPlaylist.name]))
1468+ {
1469+ self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", @"") style:UIBarButtonItemStylePlain target:self action:@selector(cancel:)] autorelease];
1470+ self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save", @"") style:UIBarButtonItemStylePlain target:self action:@selector(save:)] autorelease];
1471+
1472+ self.playlist = aPlaylist;
1473+ self.playlistListViewController = nil;
1474+ self.navigationItem.prompt = NSLocalizedString(@"Add songs to playlist", @"");
1475+
1476+ }
1477+ return self;
1478+}
1479+
1480+#pragma mark - Data Loading
1481+
1482+- (void)beginLoadingData:(NSString*)force
1483+{
1484+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1485+
1486+ NSDictionary *cachedArtists = [[DataCache sharedDataCache] objectForKey:@"SongsList"];
1487+
1488+ if (cachedArtists && ![force isEqual:@"YES"])
1489+ {
1490+ self.tableData = [cachedArtists objectForKey:@"songs"];
1491+ self.indexes = [cachedArtists objectForKey:@"indexes"];
1492+ self.groupedTableData = [cachedArtists objectForKey:@"groupedSongs"];
1493+ }
1494+ else
1495+ {
1496+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getAllSongs.view"];
1497+ NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
1498+
1499+ SongListParser *parser = [[SongListParser alloc] init];
1500+ [xmlParser setDelegate:parser];
1501+
1502+ if (![xmlParser parse])
1503+ {
1504+ [self performSelectorOnMainThread:@selector(failedLoadingData:) withObject:[xmlParser parserError] waitUntilDone:NO];
1505+ [xmlParser release];
1506+ [parser release];
1507+ [pool release];
1508+ return;
1509+ }
1510+
1511+ self.tableData = parser.songs;
1512+ if ([self.tableData count] <= 8)
1513+ {
1514+ indexed = NO;
1515+ }
1516+ self.indexes = parser.indexes;
1517+ self.groupedTableData = parser.groupedSongs;
1518+
1519+ [xmlParser release];
1520+ [parser release];
1521+
1522+ NSDictionary *cacheData = [NSDictionary dictionaryWithObjectsAndKeys:self.tableData, @"songs",
1523+ self.indexes, @"indexes", self.groupedTableData, @"groupedSongs", nil];
1524+
1525+ [[DataCache sharedDataCache] setObject:cacheData forKey:@"SongsList"];
1526+ }
1527+
1528+ [self performSelectorOnMainThread:@selector(finishLoadingData) withObject:nil waitUntilDone:NO];
1529+ [pool release];
1530+}
1531+
1532+#pragma mark - UITableView
1533+
1534+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
1535+{
1536+ static NSString *CellIdentifier = @"Cell";
1537+
1538+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
1539+ if (nil == cell)
1540+ {
1541+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
1542+ }
1543+
1544+ cell.accessoryType = UITableViewCellAccessoryNone;
1545+
1546+ Song *s = nil;
1547+
1548+ if (self.searchDisplayController.searchResultsTableView == tableView)
1549+ {
1550+ s = [self.searchResults objectAtIndex:indexPath.row];
1551+ cell.textLabel.text = s.title;
1552+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1553+ }
1554+ else
1555+ {
1556+ cell.accessoryType = UITableViewCellAccessoryNone;
1557+
1558+ if (indexed)
1559+ {
1560+ NSString *index = [self.indexes objectAtIndex:indexPath.section];
1561+ s = [[self.groupedTableData objectForKey:index] objectAtIndex:indexPath.row];
1562+ }
1563+ else
1564+ {
1565+ s = [self.tableData objectAtIndex:indexPath.row];
1566+ }
1567+ cell.textLabel.text = s.title;
1568+ }
1569+
1570+ return cell;
1571+}
1572+
1573+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
1574+{
1575+ Song *selection = nil;
1576+
1577+ if (self.searchDisplayController.searchResultsTableView == tableView)
1578+ {
1579+ selection = [self.searchResults objectAtIndex:indexPath.row];
1580+ }
1581+ else if(indexed)
1582+ {
1583+ NSString *index = [self.indexes objectAtIndex:indexPath.section];
1584+ selection = [[self.groupedTableData objectForKey:index] objectAtIndex:indexPath.row];
1585+ }
1586+ else
1587+ {
1588+ selection = [self.tableData objectAtIndex:indexPath.row];
1589+ }
1590+
1591+ UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
1592+
1593+ if (cell.accessoryType == UITableViewCellAccessoryNone) {
1594+ [self.playlist.contents addObject:selection];
1595+ cell.accessoryType = UITableViewCellAccessoryCheckmark;
1596+
1597+ } else {
1598+ [self.playlist.contents removeObject:selection];
1599+ cell.accessoryType = UITableViewCellAccessoryNone;
1600+ }
1601+
1602+ [tableView deselectRowAtIndexPath:indexPath animated:YES];
1603+}
1604+
1605+- (void)cancel:(id)sender
1606+{
1607+ self.playlist = nil;
1608+ [self dismissModalViewControllerAnimated:YES];
1609+}
1610+
1611+- (void)dealloc
1612+{
1613+ RELEASE_SAFELY(playlist);
1614+ [super dealloc];
1615+}
1616+
1617+- (void)save:(id)sender
1618+{
1619+ NSMutableSet *extraParameters = [NSMutableSet set];
1620+ if (nil != self.playlist.playlistId)
1621+ {
1622+ [extraParameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"playlistId", self.playlist.playlistId, nil]];
1623+ }
1624+ [extraParameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"name", self.playlist.name, nil]];
1625+ for (Song *song in self.playlist.contents)
1626+ {
1627+ [extraParameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"songId", song.songId, nil]];
1628+ }
1629+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"createPlaylist.view" parameters:extraParameters];
1630+ NSURLRequest *request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
1631+ NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
1632+ [connection start];
1633+}
1634+
1635+- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
1636+{
1637+ [self.playlistListViewController performSelector:@selector(reload:) withObject:nil afterDelay:0.5];
1638+ [self cancel:nil];
1639+}
1640+@end
1641\ No newline at end of file
1642
1643=== modified file 'musicstreaming/view_controllers/PlaylistListViewController.m'
1644--- musicstreaming/view_controllers/PlaylistListViewController.m 2011-04-01 14:55:49 +0000
1645+++ musicstreaming/view_controllers/PlaylistListViewController.m 2011-04-08 19:49:28 +0000
1646@@ -19,11 +19,13 @@
1647
1648 #import "PlaylistListViewController.h"
1649 #import "PlaylistViewController.h"
1650+#import "PlaylistEditViewController.h"
1651 #import "AlbumUITableViewCell.h"
1652 #import "PlaylistListParser.h"
1653 #import "AsynchronousImageViewCached.h"
1654 #import "Playlist.h"
1655 #import "DataCache.h"
1656+#import "AlertPrompt.h"
1657
1658 @implementation PlaylistListViewController
1659
1660@@ -72,6 +74,18 @@
1661
1662 #pragma mark - UITableView
1663
1664+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
1665+{
1666+ if (self.searchDisplayController.searchResultsTableView == tableView)
1667+ {
1668+ return [self.searchResults count];
1669+ }
1670+ else
1671+ {
1672+ return [self.tableData count] + 1;
1673+ }
1674+}
1675+
1676 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
1677 {
1678 static NSString *CellIdentifier = @"Cell";
1679@@ -82,17 +96,22 @@
1680 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
1681 }
1682
1683+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1684+
1685 if (self.searchDisplayController.searchResultsTableView == tableView)
1686 {
1687- Playlist *p = [searchResults objectAtIndex:indexPath.row];
1688+ Playlist *p = [self.searchResults objectAtIndex:indexPath.row];
1689 cell.textLabel.text = p.name;
1690- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1691 }
1692- else
1693+ else if(indexPath.row == 0)
1694+ {
1695+ cell.accessoryType = UITableViewCellAccessoryNone;
1696+ cell.textLabel.text = @"Create new playlist...";
1697+ }
1698+ else
1699 {
1700- cell.accessoryType = UITableViewCellAccessoryNone;
1701-
1702- Playlist *p = [self.tableData objectAtIndex:indexPath.row];
1703+ int adjusted_row = indexPath.row - 1;
1704+ Playlist *p = [self.tableData objectAtIndex:adjusted_row];
1705
1706 cell.textLabel.text = p.name;
1707 }
1708@@ -106,11 +125,25 @@
1709
1710 if (self.searchDisplayController.searchResultsTableView == tableView)
1711 {
1712- selection = [searchResults objectAtIndex:indexPath.row];
1713+ selection = [self.searchResults objectAtIndex:indexPath.row];
1714 }
1715+ else if(indexPath.row == 0)
1716+ {
1717+ // Launch a dialog to capture the new playlist's name
1718+ AlertPrompt *alert = [[[AlertPrompt alloc] initWithTitle:NSLocalizedString(@"Name New Playlist", @"")
1719+ placeholder:NSLocalizedString(@"Title", @"")
1720+ message:NSLocalizedString(@"\n", @"")
1721+ delegate:self
1722+ cancelButtonTitle:NSLocalizedString(@"Cancel",@"")
1723+ okButtonTitle:NSLocalizedString(@"Create",@"")] autorelease];
1724+ alert.tag = 1111111;
1725+ [alert show];
1726+ return;
1727+ }
1728 else
1729 {
1730- selection = [self.tableData objectAtIndex:indexPath.row];
1731+ int adjusted_row = indexPath.row - 1;
1732+ selection = [self.tableData objectAtIndex:adjusted_row];
1733 }
1734
1735 PlaylistViewController *playlistViewController = [[PlaylistViewController alloc] initWithStyle:UITableViewStylePlain];
1736@@ -119,4 +152,21 @@
1737 [playlistViewController release];
1738 }
1739
1740+#pragma mark - Alert handling
1741+
1742+- (void)alertView:(UIAlertView *)alertPrompt clickedButtonAtIndex:(NSInteger)buttonIndex
1743+{
1744+ if (1111111 == alertPrompt.tag && alertPrompt.cancelButtonIndex != buttonIndex)
1745+ {
1746+ Playlist *playlist = [[[Playlist alloc] init] autorelease];
1747+ playlist.name = [(AlertPrompt *)alertPrompt enteredText];
1748+ UINavigationController *playlistEditViewController = [PlaylistEditViewController navigableViewControllerWithPlaylist:playlist originator:self];
1749+ [self.navigationController presentModalViewController:playlistEditViewController animated:YES];
1750+ }
1751+ else
1752+ {
1753+ // Propagate up the alert handling in case it was a different alert
1754+ [super alertView:alertPrompt clickedButtonAtIndex:buttonIndex];
1755+ }
1756+}
1757 @end
1758
1759=== modified file 'musicstreaming/view_controllers/PlaylistViewController.m'
1760--- musicstreaming/view_controllers/PlaylistViewController.m 2011-04-01 03:07:07 +0000
1761+++ musicstreaming/view_controllers/PlaylistViewController.m 2011-04-08 19:49:28 +0000
1762@@ -22,6 +22,7 @@
1763 #import "PlaylistParser.h"
1764 #import "DataCache.h"
1765 #import "Song.h"
1766+#import "NSMutableSet+Extras.h"
1767
1768 @implementation PlaylistViewController
1769
1770@@ -52,15 +53,19 @@
1771 {
1772 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1773
1774- NSDictionary *cacheDict = [[DataCache sharedDataCache] objectForKey:@"Playlists"];
1775+ /*
1776+ NSDictionary *cacheDict = [[DataCache sharedDataCache] objectForKey:self.playlist.playlistId];
1777
1778 if (cacheDict && ![force isEqual:@"YES"])
1779 {
1780- self.playlist = [cacheDict objectForKey:self.playlist.playlistID];
1781+ self.playlist = [cacheDict objectForKey:@"playlist"];
1782 }
1783 else
1784 {
1785- NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getPlaylist.view" parameters:[NSDictionary dictionaryWithObject:self.playlist.playlistID forKey:@"id"]];
1786+ */
1787+ NSMutableSet *parameters = [NSMutableSet set];
1788+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", self.playlist.playlistId, nil]];
1789+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getPlaylist.view" parameters:parameters];
1790 NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
1791 PlaylistParser *parser = [[PlaylistParser alloc] init];
1792 [xmlParser setDelegate:parser];
1793@@ -73,16 +78,19 @@
1794 [pool release];
1795 return;
1796 }
1797-
1798- self.tableData = parser.songs;
1799-
1800-// NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.playlist, self.playlist.playlistID, nil];
1801-
1802-// [[DataCache sharedDataCache] setObject:dict forKey:@"Playlists"];
1803+
1804+ // self.playlist.contents = [parser.contents copy];
1805+ self.tableData = parser.contents;
1806+
1807+ // NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:self.playlist, @"playlist", nil];
1808+
1809+ // [[DataCache sharedDataCache] setObject:dict forKey:self.playlist.playlistId];
1810
1811 [xmlParser release];
1812 [parser release];
1813- }
1814+ /*
1815+ }
1816+ */
1817
1818 [pool release];
1819
1820@@ -108,14 +116,14 @@
1821
1822 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
1823 {
1824- [searchResults removeAllObjects];
1825+ [self.searchResults removeAllObjects];
1826
1827 for (Song* s in self.tableData)
1828 {
1829 NSRange titleResultsRange = [s.title rangeOfString:searchString options:NSCaseInsensitiveSearch];
1830
1831 if (titleResultsRange.length > 0)
1832- [searchResults addObject:s];
1833+ [self.searchResults addObject:s];
1834 }
1835
1836 return YES;
1837@@ -135,7 +143,7 @@
1838
1839 if (self.searchDisplayController.searchResultsTableView == tableView)
1840 {
1841- Playlist *p = [searchResults objectAtIndex:indexPath.row];
1842+ Playlist *p = [self.searchResults objectAtIndex:indexPath.row];
1843 cell.textLabel.text = p.name;
1844 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1845 }
1846@@ -154,12 +162,12 @@
1847 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
1848 {
1849 Song *song = nil;
1850- NSMutableArray *selectPlaylist = nil;
1851+ NSArray *selectPlaylist = nil;
1852
1853 if (self.searchDisplayController.searchResultsTableView == tableView)
1854 {
1855- song = [searchResults objectAtIndex:indexPath.row];
1856- selectPlaylist = searchResults;
1857+ song = [self.searchResults objectAtIndex:indexPath.row];
1858+ selectPlaylist = self.searchResults;
1859 }
1860 else
1861 {
1862
1863=== modified file 'musicstreaming/view_controllers/SettingsViewController.h'
1864--- musicstreaming/view_controllers/SettingsViewController.h 2010-10-01 03:43:56 +0000
1865+++ musicstreaming/view_controllers/SettingsViewController.h 2011-04-08 19:49:28 +0000
1866@@ -29,11 +29,9 @@
1867 // DAMAGE.
1868
1869 #import <UIKit/UIKit.h>
1870-#import "SubsonicTableViewController.h"
1871
1872-@interface SettingsViewController : SubsonicTableViewController <UITextFieldDelegate>
1873+@interface SettingsViewController : UITableViewController <UITextFieldDelegate>
1874 {
1875 }
1876-+ (UINavigationController*)navigableSettingsViewController;
1877 - (IBAction)save:(id)sender;
1878 @end
1879
1880=== modified file 'musicstreaming/view_controllers/SettingsViewController.m'
1881--- musicstreaming/view_controllers/SettingsViewController.m 2011-03-28 17:52:06 +0000
1882+++ musicstreaming/view_controllers/SettingsViewController.m 2011-04-08 19:49:28 +0000
1883@@ -31,24 +31,17 @@
1884 #import "SettingsViewController.h"
1885 #import "iSubAppDelegate.h"
1886 #import "AboutViewController.h"
1887+#import "Subsonic.h"
1888
1889 @implementation SettingsViewController
1890
1891-+ (UINavigationController*)navigableSettingsViewController;
1892-{
1893- SettingsViewController *settingsViewController = [[[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
1894- UINavigationController *nav = [[[UINavigationController alloc] initWithRootViewController:settingsViewController] autorelease];
1895- nav.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
1896- nav.navigationBar.barStyle = UIBarStyleBlack;
1897- return nav;
1898-}
1899-
1900 - (id)initWithStyle:(UITableViewStyle)style
1901 {
1902 if ((self = [super initWithStyle:style]))
1903 {
1904 self.title = NSLocalizedString(@"Settings",@"");
1905 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadCreds:) name:@"ReloadAccountCredentials" object:nil];
1906+ // self.view.backgroundColor = [UIColor orangeColor]; // Want to make this some sort of nice U1 cloudy background image
1907 }
1908 return self;
1909 }
1910
1911=== modified file 'musicstreaming/view_controllers/SongListViewController.m'
1912--- musicstreaming/view_controllers/SongListViewController.m 2011-04-01 22:35:01 +0000
1913+++ musicstreaming/view_controllers/SongListViewController.m 2011-04-08 19:49:28 +0000
1914@@ -90,7 +90,7 @@
1915
1916 if (self.searchDisplayController.searchResultsTableView == tableView)
1917 {
1918- Song *s = [searchResults objectAtIndex:indexPath.row];
1919+ Song *s = [self.searchResults objectAtIndex:indexPath.row];
1920 cell.textLabel.text = s.title;
1921 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
1922 }
1923@@ -122,8 +122,8 @@
1924
1925 if (self.searchDisplayController.searchResultsTableView == tableView)
1926 {
1927- selection = [searchResults objectAtIndex:indexPath.row];
1928- playlist = searchResults;
1929+ selection = [self.searchResults objectAtIndex:indexPath.row];
1930+ playlist = self.searchResults;
1931 }
1932 else if(indexed)
1933 {
1934
1935=== modified file 'musicstreaming/view_controllers/SongViewController.m'
1936--- musicstreaming/view_controllers/SongViewController.m 2011-03-28 17:52:06 +0000
1937+++ musicstreaming/view_controllers/SongViewController.m 2011-04-08 19:49:28 +0000
1938@@ -38,6 +38,7 @@
1939 #import <MediaPlayer/MediaPlayer.h>
1940 #import <CFNetwork/CFNetwork.h>
1941 #import "NSNumber+Extras.h"
1942+#import "NSMutableSet+Extras.h"
1943
1944 @interface SongViewController (Private)
1945 //KVO-driven stuff
1946@@ -363,7 +364,7 @@
1947 self.songLabel.text = [StreamingPlayer sharedStreamingPlayer].currentSong.title;
1948 self.trackMOfNLabel.text = [NSString stringWithFormat:@"%d of %d", [StreamingPlayer sharedStreamingPlayer].currentSongIndex+1, [[StreamingPlayer sharedStreamingPlayer].currentPlaylist count]];
1949
1950- NSURL *songURL = [[Subsonic sharedSubsonic] getStreamingURLForSongID:[StreamingPlayer sharedStreamingPlayer].currentSong.songId];
1951+ NSURL *songURL = [[Subsonic sharedSubsonic] getStreamingURLForSongId:[StreamingPlayer sharedStreamingPlayer].currentSong.songId];
1952 [StreamingPlayer sharedStreamingPlayer].songUrl = songURL;
1953
1954 iSubAppDelegate *appDelegate = (iSubAppDelegate *)[[UIApplication sharedApplication] delegate];
1955@@ -377,7 +378,10 @@
1956 else
1957 {
1958 // If not, grab it from the url and cache it
1959- NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getCoverArt.view" parameters:[NSDictionary dictionaryWithObjectsAndKeys:[StreamingPlayer sharedStreamingPlayer].currentSong.coverArtId,@"id",@"320",@"size",nil]];
1960+ NSMutableSet *parameters = [NSMutableSet set];
1961+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"id", [StreamingPlayer sharedStreamingPlayer].currentSong.coverArtId, nil]];
1962+ [parameters addKeyValueObjectFromArray:[NSArray arrayWithObjects:@"size", @"320", nil]];
1963+ NSURL *url = [[Subsonic sharedSubsonic] getBaseUrl:@"getCoverArt.view" parameters:parameters];
1964 [self.coverArtImageView loadImageFromURLString:[url absoluteString] coverArtId: [StreamingPlayer sharedStreamingPlayer].currentSong.coverArtId];
1965 }
1966 }
1967
1968=== modified file 'musicstreaming/view_controllers/SubsonicIndexedTableViewController.h'
1969--- musicstreaming/view_controllers/SubsonicIndexedTableViewController.h 2011-04-01 03:06:02 +0000
1970+++ musicstreaming/view_controllers/SubsonicIndexedTableViewController.h 2011-04-08 19:49:28 +0000
1971@@ -10,7 +10,7 @@
1972 #import "SubsonicTableViewController.h"
1973
1974
1975-@interface SubsonicIndexedTableViewController : SubsonicTableViewController <UIAlertViewDelegate>
1976+@interface SubsonicIndexedTableViewController : SubsonicTableViewController
1977 {
1978 NSMutableDictionary *groupedTableData;
1979 NSArray *indexes;
1980
1981=== modified file 'musicstreaming/view_controllers/SubsonicIndexedTableViewController.m'
1982--- musicstreaming/view_controllers/SubsonicIndexedTableViewController.m 2011-04-01 22:35:01 +0000
1983+++ musicstreaming/view_controllers/SubsonicIndexedTableViewController.m 2011-04-08 19:49:28 +0000
1984@@ -40,14 +40,12 @@
1985 {
1986 [super didReceiveMemoryWarning];
1987
1988- self.tableData = NULL;
1989 self.indexes = NULL;
1990 self.groupedTableData = NULL;
1991 }
1992
1993 - (void)dealloc
1994 {
1995- self.tableData = NULL;
1996 self.indexes = NULL;
1997 self.groupedTableData = NULL;
1998 [[NSNotificationCenter defaultCenter] removeObserver:self];
1999@@ -80,7 +78,7 @@
2000 {
2001 if (self.searchDisplayController.searchResultsTableView == tableView)
2002 {
2003- return [searchResults count];
2004+ return [self.searchResults count];
2005 }
2006 else
2007 {
2008
2009=== modified file 'musicstreaming/view_controllers/SubsonicTableViewController.h'
2010--- musicstreaming/view_controllers/SubsonicTableViewController.h 2011-04-01 03:05:21 +0000
2011+++ musicstreaming/view_controllers/SubsonicTableViewController.h 2011-04-08 19:49:28 +0000
2012@@ -25,12 +25,12 @@
2013
2014 @class Album, AsynchronousImageViewCached;
2015
2016-@interface SubsonicTableViewController : PullRefreshTableViewController <UISearchDisplayDelegate, UISearchBarDelegate>
2017+@interface SubsonicTableViewController : PullRefreshTableViewController <UIAlertViewDelegate, UISearchDisplayDelegate, UISearchBarDelegate>
2018 {
2019 MBProgressHUD *hudView;
2020 BOOL showProgressHUD;
2021 NSTimer *respondToRemoteTimer;
2022- NSArray *tableData;
2023+ NSMutableArray *tableData;
2024 NSMutableArray *searchResults;
2025 }
2026 - (id)initWithTitle:(NSString *)title;
2027@@ -49,5 +49,6 @@
2028 - (void)beginLoadingData:(NSString*)force;
2029 - (void)finishLoadingData;
2030 - (void)failedLoadingData:(NSError*)error;
2031-@property(nonatomic,retain) NSArray *tableData;
2032+@property(nonatomic,retain) NSMutableArray *tableData;
2033+@property(nonatomic,retain) NSMutableArray *searchResults;
2034 @end
2035
2036=== modified file 'musicstreaming/view_controllers/SubsonicTableViewController.m'
2037--- musicstreaming/view_controllers/SubsonicTableViewController.m 2011-04-01 14:55:49 +0000
2038+++ musicstreaming/view_controllers/SubsonicTableViewController.m 2011-04-08 19:49:28 +0000
2039@@ -26,7 +26,7 @@
2040 #import "Album.h"
2041
2042 @implementation SubsonicTableViewController
2043-@synthesize tableData;
2044+@synthesize tableData, searchResults;
2045
2046 #pragma mark -
2047 #pragma mark Initialization
2048@@ -38,7 +38,8 @@
2049 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadCredentials:) name:@"ReloadCredentials" object:nil];
2050 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetCredentials:) name:@"ResetCredentials" object:nil];
2051 self.title = title;
2052- self.tableData = [NSArray array];
2053+ self.tableData = [NSMutableArray array];
2054+ self.searchResults = [NSMutableArray array];
2055 }
2056 return self;
2057 }
2058@@ -52,7 +53,6 @@
2059 showProgressHUD = YES;
2060 respondToRemoteTimer = NULL;
2061 self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
2062- searchResults = [[NSMutableArray alloc] init];
2063 }
2064
2065 - (void)viewWillAppear:(BOOL)animated
2066@@ -263,7 +263,7 @@
2067 {
2068 if (self.searchDisplayController.searchResultsTableView == tableView)
2069 {
2070- return [searchResults count];
2071+ return [self.searchResults count];
2072 }
2073 else
2074 {
2075@@ -366,6 +366,7 @@
2076 {
2077 [hudView hide:NO];
2078 RELEASE_SAFELY(hudView);
2079+ RELEASE_SAFELY(tableData);
2080 RELEASE_SAFELY(searchResults);
2081
2082 [super dealloc];
2083@@ -375,7 +376,7 @@
2084
2085 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
2086 {
2087- [searchResults removeAllObjects];
2088+ [self.searchResults removeAllObjects];
2089
2090 for (id d in self.tableData)
2091 {

Subscribers

People subscribed via source and target branches

to all changes: