source: trunk/SapphireBrowser.m @ 65

Revision 65, 12.3 KB checked in by gbooker, 7 years ago (diff)

Use sapphire's icon for the preview.

Line 
1//
2//  SapphireBrowser.m
3//  Sapphire
4//
5//  Created by pnmerrill on 6/20/07.
6//  Copyright 2007 __MyCompanyName__. All rights reserved.
7//
8
9#import "SapphireBrowser.h"
10#import <BackRow/BackRow.h>
11#import "SapphireMetaData.h"
12#import "SapphireMarkMenu.h"
13#import "SapphireMedia.h"
14#import "SapphireVideoPlayer.h"
15#import "SapphireMediaPreview.h"
16#import "SapphireTheme.h"
17
18@interface SapphireBrowser (private)
19- (void)reloadDirectoryContents;
20- (void)processFiles:(NSArray *)files;
21- (void)filesProcessed:(NSDictionary *)files;
22- (NSMutableDictionary *)metaDataForPath:(NSString *)path;
23@end
24
25@interface BRTVShowsSortControl (bypassAccess)
26- (BRTVShowsSortSelectorStateLayer *)gimmieDate;
27- (BRTVShowsSortSelectorStateLayer *)gimmieShow;
28- (int)gimmieState;
29@end
30
31@interface BRTVShowsSortSelectorStateLayer (bypassAccess)
32- (BRTextLayer *)gimmieDate;
33- (BRTextLayer *)gimmieShow;
34@end
35
36
37@implementation BRTVShowsSortControl (bypassAccess)
38- (BRTVShowsSortSelectorStateLayer *)gimmieDate
39{
40        return _sortedByDateWidget;
41}
42
43- (BRTVShowsSortSelectorStateLayer *)gimmieShow
44{
45        return _sortedByShowWidget;
46}
47
48- (int)gimmieState
49{
50        return _state;
51}
52
53@end
54
55@implementation BRTVShowsSortSelectorStateLayer (bypassAccess)
56- (BRTextLayer *)gimmieDate
57{
58        return _dateLayer;
59}
60
61- (BRTextLayer *)gimmieShow
62{
63        return _showLayer;
64}
65
66@end
67
68@implementation SapphireBrowser
69
70- (void)replaceControlText:(BRTextLayer *)control withString:(NSString *)str
71{
72        NSMutableAttributedString  *dateString = [[control attributedString] mutableCopy];
73        [dateString replaceCharactersInRange:NSMakeRange(0, [dateString length]) withString:str];
74        [control setAttributedString:dateString];
75        [dateString release];
76}
77
78- (id) initWithScene: (BRRenderScene *) scene metaData: (SapphireDirectoryMetaData *)meta
79{
80        return [self initWithScene:scene metaData:meta predicate:NULL];
81}
82
83- (id) initWithScene: (BRRenderScene *) scene metaData: (SapphireDirectoryMetaData *)meta predicate:(SapphirePredicate *)newPredicate;
84{
85        if ( [super initWithScene: scene] == nil ) return ( nil );
86               
87        _names = [NSMutableArray new];
88        metaData = [meta retain];
89        [metaData setDelegate:self];
90        predicate = [newPredicate retain];
91        sort = [[BRTVShowsSortControl alloc] initWithScene:scene state:1];
92
93        NSRect frame = [self masterLayerFrame];
94        NSRect listFrame = [self listFrameForBounds:frame.size];
95        NSRect sortRect;
96        sortRect.size = [sort preferredSizeForScreenHeight:frame.size.height];
97        sortRect.origin.y = listFrame.origin.y * 1.5f;
98        sortRect.origin.x = (listFrame.size.width - sortRect.size.width)/2 + listFrame.origin.x;
99        listFrame.size.height -= listFrame.origin.y;
100        listFrame.origin.y *= 4.0f;
101        [self replaceControlText:[[sort gimmieDate] gimmieDate] withString:@"Select"];
102        [self replaceControlText:[[sort gimmieDate] gimmieShow] withString:@"Mark"];
103        [self replaceControlText:[[sort gimmieShow] gimmieDate] withString:@"Select"];
104        [self replaceControlText:[[sort gimmieShow] gimmieShow] withString:@"Mark"];
105        [sort setFrame:sortRect];
106        [[_listControl layer] setFrame:listFrame];
107        [self addControl:sort];
108       
109        // set the datasource *after* you've setup your array
110        [[self list] setDatasource: self] ;
111               
112        return ( self );
113}
114
115- (void)_doLayout
116{
117        [super _doLayout];
118        NSRect listFrame = [[_listControl layer] frame];
119        listFrame.size.height -= listFrame.origin.y;
120        listFrame.origin.y *= 2;
121        [[_listControl layer] setFrame:listFrame];
122}
123
124- (void)reloadDirectoryContents
125{
126        int divider = 0;
127        [metaData reloadDirectoryContents];
128        [_names removeAllObjects];
129        if(predicate == NULL)
130        {
131                [_names addObjectsFromArray:[metaData directories]];
132                divider = [_names count];
133                [_names addObjectsFromArray:[metaData files]];
134        }
135        else
136        {
137                [_names addObjectsFromArray:[metaData predicatedDirectories:predicate]];
138                divider = [_names count];
139                [_names addObjectsFromArray:[metaData predicatedFiles:predicate]];
140        }
141
142        BRListControl *list = [self list];
143        [list reload];
144        if(divider && divider != [_names count])
145                [list addDividerAtIndex:divider];
146        [[self scene] renderScene];
147}
148
149- (void) dealloc
150{
151    // always remember to deallocate your resources
152        [_names release];
153        [metaData release];
154        [predicate release];
155        [sort release];
156    [super dealloc];
157}
158
159- (void) willBePushed
160{
161    // We're about to be placed on screen, but we're not yet there
162   
163    // always call super
164    [super willBePushed];
165        [self reloadDirectoryContents];
166}
167
168- (void) wasPushed
169{
170    // We've just been put on screen, the user can see this controller's content now
171   
172    // always call super
173    [super wasPushed];
174        [metaData resumeDelayedImport];
175}
176
177- (void) willBePopped
178{
179    // The user pressed Menu, but we've not been removed from the screen yet
180   
181    // always call super
182    [super willBePopped];
183        [metaData cancelImport];
184        [metaData setDelegate:nil];
185}
186
187- (void) wasPopped
188{
189    // The user pressed Menu, removing us from the screen
190   
191    // always call super
192    [super wasPopped];
193}
194
195- (void) willBeBuried
196{
197    // The user just chose an option, and we will be taken off the screen
198   
199    // always call super
200        [metaData cancelImport];
201    [super willBeBuried];
202}
203
204- (void) wasBuriedByPushingController: (BRLayerController *) controller
205{
206    // The user chose an option and this controller os no longer on screen
207   
208    // always call super
209    [super wasBuriedByPushingController: controller];
210}
211
212- (void) willBeExhumed
213{
214    // the user pressed Menu, but we've not been revealed yet
215   
216        id controller = [[self stack] peekController];
217        if([controller isKindOfClass:[BRVideoPlayerController class]])
218        {
219                BRVideoPlayer *player = [(BRVideoPlayerController *)controller player];
220                float elapsed = [player elapsedPlaybackTime];
221                float duration = [player trackDuration];
222                if(elapsed / duration > 0.9f)
223                {
224                        [currentPlayFile setWatched:YES];
225                        [[self list] reload];
226                        [[self scene] renderScene];
227                }
228                if(elapsed < duration - 2)
229                        [currentPlayFile setResumeTime:[player elapsedPlaybackTime]];
230                else
231                        [currentPlayFile setResumeTime:0];
232                [currentPlayFile writeMetaData];
233        }
234        [currentPlayFile release];
235        currentPlayFile = nil;
236        [self reloadDirectoryContents];
237    // always call super
238    [super willBeExhumed];
239}
240
241- (void) wasExhumedByPoppingController: (BRLayerController *) controller
242{
243    // handle being revealed when the user presses Menu
244   
245    // always call super
246    [super wasExhumedByPoppingController: controller];
247        if([_names count] == 0)
248                [[self stack] popController];
249        else
250                [metaData resumeDelayedImport];
251}
252
253- (long) itemCount
254{
255    // return the number of items in your menu list here
256        if([_names count])
257                return ( [ _names count]);
258        // Put up an empty item
259        return 1;
260}
261
262- (id<BRMenuItemLayer>) itemForRow: (long) row
263{
264/*
265    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
266    // return that object, it will be used to display the list item.
267    return ( nil );
268*/
269        if( [_names count] == 0)
270        {
271                BRAdornedMenuItemLayer *result = [BRAdornedMenuItemLayer adornedMenuItemWithScene:[self scene]];
272                [[result textItem] setTitle:@"< EMPTY >"];
273                return result;
274        }
275        if( row >= [_names count] ) return ( nil ) ;
276       
277        NSString *name = [_names objectAtIndex:row];
278        // Pad filename to correcrtly display gem icons
279        BRAdornedMenuItemLayer * result = nil;
280        BOOL watched = NO;
281        BOOL favorite = NO ;
282        if([[metaData directories] containsObject:name])
283        {
284                result = [BRAdornedMenuItemLayer adornedFolderMenuItemWithScene: [self scene]] ;
285                SapphireDirectoryMetaData *meta = [metaData metaDataForDirectory:name];
286                watched = [meta watchedForPredicate:predicate];
287        }
288        else
289        {
290                result = [BRAdornedMenuItemLayer adornedMenuItemWithScene: [self scene]] ;
291                SapphireFileMetaData *meta = [metaData metaDataForFile:name];
292                if(meta != nil)
293                {
294                        [[result textItem] setRightJustifiedText:[meta sizeString]];
295                        watched = [meta watched];
296                        favorite = [meta favorite] ;
297                }
298        }
299        if(!watched)
300                [result setLeftIcon:[[SapphireTheme sharedTheme] blueGemForScene:[self scene]]];
301        else if(favorite)[result setLeftIcon:[[SapphireTheme sharedTheme] yellowGemForScene:[self scene]]];
302                       
303        // add text
304        name=[@"   " stringByAppendingString: name] ;
305        [[result textItem] setTitle: name] ;
306                               
307        return ( result ) ;
308}
309
310- (NSString *) titleForRow: (long) row
311{
312
313        if ( row >= [ _names count] ) return ( nil );
314       
315        NSString *result = [ _names objectAtIndex: row] ;
316       
317        return ([@"   " stringByAppendingString: result] ) ;
318}
319
320- (long) rowForTitle: (NSString *) title
321{
322    long result = -1;
323    long i, count = [self itemCount];
324    for ( i = 0; i < count; i++ )
325    {
326        if ( [title isEqualToString: [self titleForRow: i]] )
327        {
328            result = i;
329            break;
330        }
331    }
332   
333    return ( result );
334}
335
336- (void) itemSelected: (long) row
337{
338    // This is called when the user presses play/pause on a list item
339       
340        if([_names count] == 0)
341        {
342                [[self stack] popController];
343                return;
344        }
345       
346        NSString *name = [_names objectAtIndex:row];
347//      name=[@"  " stringByAppendingString: name] ;
348        NSString *dir = [metaData path];
349       
350        if([sort gimmieState] == 2)
351        {
352                id meta = nil;
353                if([[metaData directories] containsObject:name])
354                        meta = [metaData metaDataForDirectory:name];
355                else
356                        meta = [metaData metaDataForFile:name];
357                id controller = [[SapphireMarkMenu alloc] initWithScene:[self scene] metaData:meta];
358                [(SapphireMarkMenu *)controller setPredicate:predicate];
359                [[self stack] pushController:controller];
360                [controller release];
361                return;
362        }
363       
364        if([[metaData directories] containsObject:name])
365        {
366                id controller = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:[metaData metaDataForDirectory:name] predicate:predicate];
367                [controller setListTitle:name];
368                [controller setListIcon:[self listIcon]];
369                [[self stack] pushController:controller];
370                [controller release];
371        }
372        else
373        {
374                BRVideoPlayerController *controller = [[BRVideoPlayerController alloc] initWithScene:[self scene]];
375               
376                currentPlayFile = [[metaData metaDataForFile:name] retain];
377                [controller setAllowsResume:YES];
378               
379                NSString *path = [dir stringByAppendingPathComponent:name];
380                NSURL *url = [NSURL fileURLWithPath:path];
381                SapphireMedia *asset  =[[SapphireMedia alloc] initWithMediaURL:url];
382                [asset setResumeTime:[currentPlayFile resumeTime]];
383
384                SapphireVideoPlayer *player = [[SapphireVideoPlayer alloc] init];
385                [player setMetaData:currentPlayFile];
386                NSError *error = nil;
387                [player setMedia:asset error:&error];
388               
389                [controller setVideoPlayer:player];
390                [[self stack] pushController:controller];
391
392                [asset release];
393                [player release];
394                [controller release];
395        }
396}
397
398- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
399{
400    // If subclassing BRMediaMenuController, this function is called when the selection cursor
401    // passes over an item.
402        if(item >= [_names count])
403                return nil;
404        NSString *name = [_names objectAtIndex:item];
405        if([[metaData files] containsObject:name])
406        {
407                SapphireFileMetaData *fileMeta = [metaData metaDataForFile:name];
408               
409                SapphireMediaPreview *preview = [[SapphireMediaPreview alloc] initWithScene:[self scene]];
410               
411//              NSURL *url = [NSURL fileURLWithPath:@"/System/Library/PrivateFrameworks/BackRow.framework/Resources/Movies.png"];
412                NSURL *url = [NSURL fileURLWithPath:[[[NSBundle bundleForClass:[self class]] bundlePath] stringByAppendingString:@"/Contents/Resources/ApplianceIcon.png"]];
413                CGImageSourceRef sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
414                CGImageRef imageRef = nil;
415                if(sourceRef)
416                {
417                        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
418                        CFRelease(sourceRef);
419                }
420                if(imageRef)
421                {
422                        [preview setImage:imageRef];
423                        CFRelease(imageRef);
424                }
425               
426                NSMutableDictionary *attrs = [[[BRThemeInfo sharedTheme] metadataSummaryFieldAttributes] mutableCopy];
427                NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
428                float tabLoc = [[self masterLayer] frame].size.width * 0.4f;
429                NSTextTab *myTab = [[NSTextTab alloc] initWithType:NSRightTabStopType location:tabLoc];
430                NSArray *tabs = [NSArray arrayWithObject:myTab];
431                [myTab release];
432                [style setTabStops:tabs];
433                [attrs removeObjectForKey:@"CTTextAlignment"];
434                [attrs setObject:style forKey:NSParagraphStyleAttributeName];
435                [preview setText:[[[NSAttributedString alloc] initWithString:[fileMeta metaDataDescription] attributes:attrs] autorelease]];
436                [attrs release];
437               
438                return [preview autorelease];
439        }
440    return ( nil );
441}
442
443- (BOOL)brEventAction:(id)fp8
444{
445        [metaData resumeDelayedImport];
446        return [super brEventAction:fp8];
447}
448
449- (void)updateComplete
450{
451        BRListControl *list = [self list];
452        [list reload];
453        [[self scene] renderScene];
454}
455
456@end
Note: See TracBrowser for help on using the repository browser.