source: branches/CoreData/SapphireFrappliance/FRAppliance/SapphireApplianceController.m @ 626

Revision 626, 19.6 KB checked in by gbooker, 6 years ago (diff)

Massive speed increase of the tvshow, cast, director, and genre virtual directories. Some of these are now even faster than the old ones.

Line 
1/*
2 * SapphireApplianceController.m
3 * Sapphire
4 *
5 * Created by pnmerrill on Jun. 20, 2007.
6 * Copyright 2007 Sapphire Development Team and/or www.nanopi.net
7 * All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
10 * General Public License as published by the Free Software Foundation; either version 3 of the License,
11 * or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
14 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15 * Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along with this program; if not,
18 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 */
20
21#import "SapphireApplianceController.h"
22#import <BackRow/BackRow.h>
23#include <dlfcn.h>
24#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
25#import <SapphireCompatClasses/SapphireDVDLoadingController.h>
26
27#import "SapphireBrowser.h"
28#import "SapphireDirectoryMetaData.h"
29#import "SapphireFileMetaData.h"
30#import "SapphireSettings.h"
31#import "SapphireTheme.h"
32#import "SapphireCollectionDirectory.h"
33#import "CoreDataSupportFunctions.h"
34#import "SapphireEpisode.h"
35
36#import "SapphireImporterDataMenu.h"
37#import "SapphireXMLFileDataImporter.h"
38#import "SapphireFileDataImporter.h"
39#import "SapphireTVShowImporter.h"
40#import "SapphireMovieImporter.h"
41#import "SapphireAllImporter.h"
42#import "SapphireImportHelper.h"
43#import "SapphireMetaDataSupport.h"
44#import "SapphireEntityDirectory.h"
45#import "SapphireTVShow.h"
46#import "SapphireMovieDirectory.h"
47
48NSString *SAPPHIRE_MANAGED_OBJECT_CONTEXT_CLOSING =     @"SapphireManagedObjectContextClosing";
49
50#define BROWSER_MENU_ITEM               BRLocalizedString(@"  Browse", @"Browser Menu Item")
51#define ALL_IMPORT_MENU_ITEM    BRLocalizedString(@"  Import All Data", @"All Importer Menu Item")
52#define SETTINGS_MENU_ITEM              BRLocalizedString(@"  Settings", @"Settings Menu Item")
53#define RESET_MENU_ITEM                 BRLocalizedString(@"  Reset the thing already", @"UI Quit")
54
55@interface SapphireApplianceController (private)
56- (void)setMenuFromSettings;
57- (void)recreateMenu;
58@end
59
60@implementation SapphireApplianceController
61
62static NSArray *predicates = nil;
63
64NSPredicate *unwatched = nil;
65NSPredicate *favorite = nil;
66NSPredicate *skipJoin = nil;
67NSPredicate *strictUnwatched = nil;
68NSPredicate *strictFavorite = nil;
69
70+ (void)initialize
71{
72        skipJoin = [[NSPredicate predicateWithFormat:@"joinedToFile == nil"] retain];
73        unwatched = [[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"watched == NO"], skipJoin, nil]] retain];
74        favorite = [[NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"favorite == YES"], skipJoin, nil]] retain];
75//      NSPredicate *topShows = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:[NSPredicate predicateWithFormat:@"top == YES"], skipJoin, nil]];
76        predicates = [[NSArray alloc] initWithObjects:unwatched, favorite/*, topShows*/, nil];
77        strictUnwatched = [[NSPredicate predicateWithFormat:@"watched == NO"] retain];
78        strictFavorite = [[NSPredicate predicateWithFormat:@"favorite == YES"] retain];
79}
80
81+ (NSPredicate *)predicate
82{
83        SapphireSettings *settings = [SapphireSettings sharedSettings];
84        int index = [settings indexOfLastPredicate];
85        if(index == NSNotFound)
86                return skipJoin;
87        return [predicates objectAtIndex:index];
88}
89
90+ (NSPredicate *)nextPredicate
91{
92        SapphireSettings *settings = [SapphireSettings sharedSettings];
93        int index = [settings indexOfLastPredicate];
94        int newIndex;
95        switch(index)
96        {
97                case NSNotFound:
98                        newIndex = 0;
99                        if([settings displayUnwatched])
100                                break;
101                case 0:
102                        newIndex = 1;
103                        if([settings displayFavorites])
104                                break;
105//              case 1:
106//                      newIndex = 2;
107//                      if([settings displayTopShows])
108//                              break;
109                default:
110                        newIndex = NSNotFound;
111        }
112        [settings setIndexOfLastPredicate:newIndex];
113        if(newIndex == NSNotFound)
114                return skipJoin;
115        return [predicates objectAtIndex:newIndex];
116}
117
118+ (PredicateType)predicateType
119{
120        return [[SapphireSettings sharedSettings] indexOfLastPredicate];
121}
122
123+ (void)setPredicateType:(PredicateType)type
124{
125        [[SapphireSettings sharedSettings] setIndexOfLastPredicate:type];
126}
127
128+ (NSPredicate *)unfilteredPredicate
129{
130        return skipJoin;
131}
132
133+ (NSPredicate *)unwatchedPredicate
134{
135        return strictUnwatched;
136}
137
138+ (NSPredicate *)favoritePredicate
139{
140        return strictFavorite;
141}
142
143+ (BRTexture *)gemForPredicate:(NSPredicate *)predicate
144{
145        SapphireTheme *theme = [SapphireTheme sharedTheme];
146        if(predicate == nil)
147                return [theme gem:RED_GEM_KEY];
148        int index = [predicates indexOfObject:predicate];
149        switch (index) {
150                case 0:
151                        return [theme gem:BLUE_GEM_KEY];
152                case 1:
153                        return [theme gem:YELLOW_GEM_KEY];
154                case 2:
155                        return [theme gem:GREEN_GEM_KEY];
156        }
157        return [theme gem:RED_GEM_KEY];
158}
159
160+ (NSString *)keyForFilterPredicate:(NSPredicate *)filter andCheckPredicate:(NSPredicate *)check
161{
162        int found = 0;
163        if(filter == skipJoin)
164                found = 1;
165        else if (filter == unwatched)
166                found = 2;
167        else if (filter == favorite)
168                found = 4;
169        else if (filter != nil)
170                return [[filter description] stringByAppendingString:[check description]];
171       
172        if(check == strictUnwatched)
173                found |= 2;
174        else if (check == strictFavorite)
175                found |= 4;
176        else if (check != nil)
177                return [[filter description] stringByAppendingString:[check description]];
178       
179        switch (found) {
180                case 0:
181                        return @"nil";
182                case 1:
183                        return @"S";
184                case 2:
185                        return @"W";
186                case 3:
187                        return @"SW";
188                case 4:
189                        return @"F";
190                case 5:
191                        return @"SF";
192                case 6:
193                        return @"WF";
194                case 7:
195                        return @"SWF";
196        }
197        return nil;
198}
199
200+ (void)logException:(NSException *)e
201{
202        NSMutableString *ret = [NSMutableString stringWithFormat:@"Exception: %@ %@\n", [e name], [e reason]];
203        if([e respondsToSelector:@selector(backtrace)])
204        {
205                [ret appendFormat:@"%@\n%@", e, [(BRBacktracingException *)e backtrace]];
206                Dl_info info;
207                if(dladdr(&predicates, &info))
208                        [ret appendFormat:@"Sapphire is at 0x%X", info.dli_fbase];
209        }
210        else
211        {
212                NSArray *addrs = [SapphireFrontRowCompat callStackReturnAddressesForException:e];
213                int i, count = [addrs count];
214                NSMutableDictionary *mapping = [NSMutableDictionary dictionary];
215                for(i=0; i<count; i++)
216                {
217                        Dl_info info;
218                        const void *addr = [[addrs objectAtIndex:i] pointerValue];
219                        if(dladdr(addr, &info))
220                                [mapping setObject:[NSString stringWithCString:info.dli_fname] forKey:[NSValue valueWithPointer:info.dli_fbase]];
221                        [ret appendFormat:@" 0x%X", addr];
222                }
223                NSEnumerator *mappingEnum = [mapping keyEnumerator];
224                NSValue *key = nil;
225                while((key = [mappingEnum nextObject]) != nil)
226                        [ret appendFormat:@"\n0x%X\t%@", [key pointerValue], [mapping objectForKey:key]];
227        }
228        NSLog(@"%@", ret);     
229}
230
231+ (NSString *) rootMenuLabel
232{
233        return (@"net.pmerrill.Sapphire" );
234}
235
236+ (BOOL)upgradeNeeded
237{
238        NSFileManager *fm = [NSFileManager defaultManager];
239        NSString *storeFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.sapphireData"];
240        BOOL exists = [fm fileExistsAtPath:storeFile];
241        NSString *plistFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.plist"];
242        BOOL oldExists = [fm fileExistsAtPath:plistFile];
243        return !exists && oldExists;
244}
245
246- (id) initWithScene: (BRRenderScene *) scene
247{
248        self = [super initWithScene:scene];
249       
250        //Setup the theme's scene
251        SapphireTheme *theme = [SapphireTheme sharedTheme];
252        [theme setScene:[self scene]];
253       
254        NSString *storeFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.sapphireData"];
255        moc = [[NSManagedObjectContext alloc] init];
256        [moc setUndoManager:nil];
257        NSString *mopath = [[NSBundle bundleForClass:[self class]] pathForResource:@"Sapphire" ofType:@"mom"];
258        NSURL *mourl = [NSURL fileURLWithPath:mopath];
259        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:mourl];
260        NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
261        [moc setPersistentStoreCoordinator:coord];
262        [coord release];
263       
264        NSURL *storeUrl = [NSURL fileURLWithPath:storeFile];
265        NSError *error = nil;
266        [coord addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];
267        [SapphireDirectoryMetaData createDirectoryWithPath:@"/" parent:nil inContext:moc];
268       
269        settings                                                                = [[SapphireSettings alloc] initWithScene:[self scene] settingsPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/settings.plist"] context:moc];
270        [self setListTitle:                                             BRLocalizedString(@"Main Menu", @"")];
271        [settings setListTitle:                                 BRLocalizedString(@" Settings", @"Settings Menu Item")] ;
272        [settings setListIcon:                                  [theme gem:GEAR_GEM_KEY]];
273        [[self list] setDatasource:self];
274        if([SapphireFrontRowCompat usingFrontRow] && ![SapphireFrontRowCompat usingTakeTwo])
275        {
276                NSString *myBundlePath = [[NSBundle bundleForClass:[self class]] bundlePath] ;
277                NSString *onlyPath = [myBundlePath stringByAppendingPathComponent:@"/Contents/Frameworks/LeopardOnly.framework"];
278                NSBundle *only = [NSBundle bundleWithPath:onlyPath];
279                Class onlyClass = [only principalClass];
280                leoOnly = [[onlyClass alloc] initWithContext:moc];
281        }
282        mountsOnly = NO;
283       
284        return self;
285}
286
287- (void)dealloc
288{
289        [leoOnly release];
290        [names release];
291        [controllers release];
292        [masterNames release];
293        [masterControllers release];
294        [moc release];
295        [SapphireSettings relinquishSettings];
296        [settings release];
297        [SapphireImportHelper relinquishHelper];
298        [super dealloc];
299}
300
301- (void)recreateMenu
302{
303        names = [[NSMutableArray alloc] init];
304        controllers = [[NSMutableArray alloc] init];
305        if(mountsOnly)
306        {
307                masterNames = [[NSArray alloc] init];
308                masterControllers = [[NSArray alloc] init];
309        }
310        else
311        {
312                SapphireImporterDataMenu *allImporter   = [self allImporter];
313                NSMutableArray *mutableMasterNames = [[NSMutableArray alloc] init];
314                NSMutableArray *mutableMasterControllers = [[NSMutableArray alloc] init];
315               
316                SapphireBrowser *tvBrowser = [self tvBrowser];
317                [mutableMasterNames addObject:BRLocalizedString(@"  TV Shows", nil)];
318                [mutableMasterControllers addObject:tvBrowser];
319               
320                SapphireBrowser *movieBrowser = [self movieBrowser];
321                [mutableMasterNames addObject:BRLocalizedString(@"  Movies", nil)];
322                [mutableMasterControllers addObject:movieBrowser];
323               
324                [mutableMasterNames addObjectsFromArray:[NSArray arrayWithObjects:
325                                                                                                 ALL_IMPORT_MENU_ITEM,
326                                                                                                 SETTINGS_MENU_ITEM,
327                                                                                                 RESET_MENU_ITEM,
328                                                                                                 nil]];
329                [mutableMasterControllers addObjectsFromArray:[NSArray arrayWithObjects:
330                                                                                                           allImporter,
331                                                                                                           settings,
332                                                                                                           nil]];
333                masterNames = [[NSArray alloc] initWithArray:mutableMasterNames];
334                masterControllers = [[NSArray alloc] initWithArray:mutableMasterControllers];
335                [mutableMasterNames release];
336                [mutableMasterControllers release];             
337        }
338        [self setMenuFromSettings];
339}
340
341NSArray *showEntityFetch(NSManagedObjectContext *moc, NSPredicate *filterPredicate)
342{
343        NSPredicate *fetchPredicate = [NSPredicate predicateWithFormat:@"tvEpisode != nil"];
344        NSPredicate *finalPred;
345        if(filterPredicate == nil)
346                finalPred = fetchPredicate;
347        else
348                finalPred = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:filterPredicate, fetchPredicate, nil]];
349        NSArray *files = doFetchRequest(SapphireFileMetaDataName, moc, finalPred);
350
351        NSSet *epIds = [NSSet setWithArray:[files valueForKeyPath:@"tvEpisode.objectID"]];
352        NSPredicate *epPred = [NSPredicate predicateWithFormat:@"SELF IN %@", epIds];
353        NSArray *episodes = doFetchRequest(SapphireEpisodeName, moc, epPred);
354
355        NSSet *showIds = [NSSet setWithArray:[episodes valueForKeyPath:@"tvShow.objectID"]];
356        NSPredicate *showPred = [NSPredicate predicateWithFormat:@"SELF IN %@", showIds];
357
358        return doFetchRequest(SapphireTVShowName, moc, showPred);
359}
360
361- (SapphireBrowser *)tvBrowser
362{
363        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
364        SapphireEntityDirectory *tvDir = [[SapphireEntityDirectory alloc] initWithEntityFetch:showEntityFetch inContext:moc];
365        [tvDir setMetaFileFetchPredicate:[NSPredicate predicateWithFormat:@"tvEpisode != nil"]];
366        SapphireBrowser *tvBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:tvDir];
367        [tvDir release];
368        [tvBrowser setListTitle:BRLocalizedString(@" TV Shows", nil)];
369        [tvBrowser setListIcon:predicateGem];
370        return [tvBrowser autorelease];
371}
372
373- (SapphireBrowser *)movieBrowser
374{
375        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
376        SapphireMovieDirectory *movieDir = [[SapphireMovieDirectory alloc] initWithContext:moc];
377        SapphireBrowser *movieBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:movieDir];
378        [movieDir release];
379        [movieBrowser setListTitle:BRLocalizedString(@" Movies", nil)];
380        [movieBrowser setListIcon:predicateGem];
381        return [movieBrowser autorelease];     
382}
383
384- (void)setToMountsOnly
385{
386        [self setListTitle:BRLocalizedString(@"Collections", @"")];
387        mountsOnly = YES;
388}
389
390- (SapphireImporterDataMenu *)allImporter
391{
392        SapphireXMLFileDataImporter *xmlImpr = [[SapphireXMLFileDataImporter alloc] init];
393        SapphireFileDataImporter *fileImp = [[SapphireFileDataImporter alloc] init];
394        SapphireTVShowImporter *tvImp = [[SapphireTVShowImporter alloc] initWithContext:moc];
395        SapphireMovieImporter *movImp = [[SapphireMovieImporter alloc] initWithContext:moc];
396        SapphireAllImporter *allImp = [[SapphireAllImporter alloc] initWithImporters:[NSArray arrayWithObjects:xmlImpr,tvImp,movImp,fileImp,nil]];
397        [xmlImpr release];
398        [fileImp release];
399        [tvImp release];
400        [movImp release];
401        SapphireImporterDataMenu *ret = [[SapphireImporterDataMenu alloc] initWithScene:[self scene] context:moc importer:allImp];
402        [allImp release];
403        return [ret autorelease];
404}
405
406- (SapphireSettings *)settings
407{
408        return settings;
409}
410
411- (void)setMenuFromSettings
412{
413        [names removeAllObjects];
414        [controllers removeAllObjects];
415        [names addObjectsFromArray:masterNames];
416        [controllers addObjectsFromArray:masterControllers];
417        NSMutableDictionary *dvds = [NSMutableDictionary dictionary];
418        NSEnumerator *dvdEnum = [[NSClassFromString(@"BRDiskArbHandler") mountedDVDs] objectEnumerator];
419        BRDiskInfo *dvdInfo;
420        while((dvdInfo = [dvdEnum nextObject]) != nil)
421        {
422                NSString *mountpoint = [dvdInfo mountpoint];
423                [dvds setObject:dvdInfo forKey:mountpoint];
424        }
425       
426        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
427        NSEnumerator *browserPointsEnum = [[SapphireCollectionDirectory availableCollectionDirectoriesInContext:moc] objectEnumerator];
428        SapphireCollectionDirectory *browserPoint = nil;
429        int index = 2;
430        if(mountsOnly)
431                index = 0;
432        while((browserPoint = [browserPointsEnum nextObject]) != nil)
433        {
434                if([browserPoint hiddenValue])
435                        continue;
436                id controller = nil;
437                if((dvdInfo = [dvds objectForKey:browserPoint]) != nil)
438                {
439                        BRDVDMediaAsset *asset = [BRDVDMediaAsset assetFromDiskInfo:dvdInfo];
440                        controller = [[SapphireDVDLoadingController alloc] initWithScene:[self scene] forAsset:asset];
441                        [controller retain];
442                }
443                else
444                {
445                        SapphireDirectoryMetaData *meta = [browserPoint directory];
446                        controller = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:meta];
447                        [controller setListTitle:[NSString stringWithFormat:@" %@",[[meta path] lastPathComponent]]];
448                        [controller setListIcon:predicateGem];
449                }
450                if(controller != nil)
451                {
452                        [names insertObject:[NSString stringWithFormat:@"  %@", [[browserPoint directory] path]] atIndex:index];
453                        [controllers insertObject:controller atIndex:index];
454                        [controller release];
455                        index++;
456                }
457        }       
458       
459        if([settings disableUIQuit] && !mountsOnly)
460                [names removeLastObject];
461}
462
463- (void) willBePushed
464{
465    // We're about to be placed on screen, but we're not yet there
466    [self recreateMenu];
467        [[self list] reload];
468    // always call super
469    [super willBePushed];
470}
471
472- (void) wasPushed
473{
474    // We've just been put on screen, the user can see this controller's content now
475   
476    // always call super
477    [super wasPushed];
478}
479
480- (void) willBePopped
481{
482    // The user pressed Menu, but we've not been removed from the screen yet
483   
484    // always call super
485    [super willBePopped];
486}
487
488- (void) wasPopped
489{
490    // The user pressed Menu, removing us from the screen
491   
492    // always call super
493    [super wasPopped];
494}
495
496- (void) willBeBuried
497{
498    // The user just chose an option, and we will be taken off the screen
499   
500    // always call super
501    [super willBeBuried];
502}
503
504- (void) wasBuriedByPushingController: (BRLayerController *) controller
505{
506    // The user chose an option and this controller os no longer on screen
507   
508    // always call super
509    [super wasBuriedByPushingController: controller];
510}
511
512- (void) willBeExhumed
513{
514    // the user pressed Menu, but we've not been revealed yet
515   
516    // always call super
517    [super willBeExhumed];
518        [self setMenuFromSettings];
519        [[self list] reload];
520        [SapphireFrontRowCompat renderScene:[self scene]];
521}
522
523- (void) wasExhumedByPoppingController: (BRLayerController *) controller
524{
525    // handle being revealed when the user presses Menu
526   
527    // always call super
528    [super wasExhumedByPoppingController: controller];
529}
530
531- (long) itemCount
532{
533    // return the number of items in your menu list here
534        return ( [ names count]);
535}
536
537- (id<BRMenuItemLayer>) itemForRow: (long) row
538{
539/*
540    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
541    // return that object, it will be used to display the list item.
542*/
543        if( row > [names count] ) return ( nil ) ;
544       
545        BRAdornedMenuItemLayer * result = nil ;
546        NSString *name = [names objectAtIndex:row];
547        result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:YES];
548       
549        SapphireTheme *theme = [SapphireTheme sharedTheme];
550        if([name isEqual: ALL_IMPORT_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:IMPORT_GEM_KEY] forMenu:result];
551        else if([name isEqual: SETTINGS_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:GEAR_GEM_KEY] forMenu:result];
552        else if([name isEqual: RESET_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:FRONTROW_GEM_KEY] forMenu:result];
553        else if([name isEqual: @"  TV Shows"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:TV_GEM_KEY] forMenu:result];
554        else if([name isEqual: @"  Movies"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:MOV_GEM_KEY] forMenu:result];
555        else [SapphireFrontRowCompat setLeftIcon:[SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]] forMenu:result];
556       
557        // add text
558        [SapphireFrontRowCompat setTitle:name forMenu:result];
559                               
560        return ( result ) ;
561}
562
563- (NSString *) titleForRow: (long) row
564{
565
566        if ( row > [ names count] ) return ( nil );
567       
568        NSString *result = [ names objectAtIndex: row] ;
569        return ( result ) ;
570/*
571    // return the title for the list item at the given index here
572    return ( @"Sapphire" );
573*/
574}
575
576- (long) rowForTitle: (NSString *) title
577{
578    long result = -1;
579    long i, count = [self itemCount];
580    for ( i = 0; i < count; i++ )
581    {
582        if ( [title isEqualToString: [self titleForRow: i]] )
583        {
584            result = i;
585            break;
586        }
587    }
588   
589    return ( result );
590}
591
592- (void) itemSelected: (long) row
593{
594    // This is called when the user presses play/pause on a list item
595        if(row == [controllers count])
596                [[NSApplication sharedApplication] terminate:self];
597        id controller = [controllers objectAtIndex:row];
598       
599        // This if statement needs to be done in a much more elegant way
600        [[self stack] pushController:controller];
601}
602
603- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
604{
605    // If subclassing BRMediaMenuController, this function is called when the selection cursor
606    // passes over an item.
607    return ( nil );
608}
609
610@end
Note: See TracBrowser for help on using the repository browser.