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

Revision 560, 16.6 KB checked in by gbooker, 6 years ago (diff)

Byebye SapphireFile? (protocol); we no longer need you *sniff*

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 "SapphireSettings.h"
30#import "SapphireTheme.h"
31#import "SapphireCollectionDirectory.h"
32
33#import "SapphireImporterDataMenu.h"
34#import "SapphireXMLFileDataImporter.h"
35#import "SapphireFileDataImporter.h"
36#import "SapphireTVShowImporter.h"
37#import "SapphireMovieImporter.h"
38#import "SapphireAllImporter.h"
39#import "SapphireImportHelper.h"
40#import "SapphireMetaDataSupport.h"
41#import "SapphireEntityDirectory.h"
42#import "SapphireTVShow.h"
43#import "SapphireMovieDirectory.h"
44
45#define BROWSER_MENU_ITEM               BRLocalizedString(@"  Browse", @"Browser Menu Item")
46#define ALL_IMPORT_MENU_ITEM    BRLocalizedString(@"  Import All Data", @"All Importer Menu Item")
47#define SETTINGS_MENU_ITEM              BRLocalizedString(@"  Settings", @"Settings Menu Item")
48#define RESET_MENU_ITEM                 BRLocalizedString(@"  Reset the thing already", @"UI Quit")
49
50@interface SapphireApplianceController (private)
51- (void)setMenuFromSettings;
52- (void)recreateMenu;
53@end
54
55@implementation SapphireApplianceController
56
57static NSArray *predicates = nil;
58
59NSPredicate *unwatched = nil;
60NSPredicate *favorite = nil;
61
62+ (void)initialize
63{
64        unwatched = [NSPredicate predicateWithFormat:@"watched == NO"];
65        favorite = [NSPredicate predicateWithFormat:@"favorite == YES"];
66        NSPredicate *topShows = [NSPredicate predicateWithFormat:@"top == YES"];
67        predicates = [[NSArray alloc] initWithObjects:unwatched, favorite, topShows, nil];
68}
69
70+ (NSPredicate *)predicate
71{
72        SapphireSettings *settings = [SapphireSettings sharedSettings];
73        int index = [settings indexOfLastPredicate];
74        if(index == NSNotFound)
75                return nil;
76        return [predicates objectAtIndex:index];
77}
78
79+ (NSPredicate *)nextPredicate
80{
81        SapphireSettings *settings = [SapphireSettings sharedSettings];
82        int index = [settings indexOfLastPredicate];
83        int newIndex;
84        switch(index)
85        {
86                case NSNotFound:
87                        newIndex = 0;
88                        if([settings displayUnwatched])
89                                break;
90                case 0:
91                        newIndex = 1;
92                        if([settings displayFavorites])
93                                break;
94                case 1:
95                        newIndex = 2;
96                        if([settings displayTopShows])
97                                break;
98                default:
99                        newIndex = NSNotFound;
100        }
101        [settings setIndexOfLastPredicate:newIndex];
102        if(newIndex == NSNotFound)
103                return nil;
104        return [predicates objectAtIndex:newIndex];
105}
106
107+ (NSPredicate *)unwatchedPredicate
108{
109        return unwatched;
110}
111
112+ (NSPredicate *)favoritePredicate
113{
114        return favorite;
115}
116
117+ (BRTexture *)gemForPredicate:(NSPredicate *)predicate
118{
119        SapphireTheme *theme = [SapphireTheme sharedTheme];
120        if(predicate == nil)
121                return [theme gem:RED_GEM_KEY];
122        int index = [predicates indexOfObject:predicate];
123        switch (index) {
124                case 0:
125                        return [theme gem:BLUE_GEM_KEY];
126                case 1:
127                        return [theme gem:YELLOW_GEM_KEY];
128                case 2:
129                        return [theme gem:GREEN_GEM_KEY];
130        }
131        return nil;
132}
133
134+ (void)logException:(NSException *)e
135{
136        NSMutableString *ret = [NSMutableString stringWithFormat:@"Exception:"];
137        if([e respondsToSelector:@selector(backtrace)])
138        {
139                [ret appendFormat:@"%@\n%@", e, [(BRBacktracingException *)e backtrace]];
140                Dl_info info;
141                if(dladdr(&predicates, &info))
142                        [ret appendFormat:@"Sapphire is at 0x%X", info.dli_fbase];
143        }
144        else
145        {
146                NSArray *addrs = [SapphireFrontRowCompat callStackReturnAddressesForException:e];
147                int i, count = [addrs count];
148                NSMutableDictionary *mapping = [NSMutableDictionary dictionary];
149                for(i=0; i<count; i++)
150                {
151                        Dl_info info;
152                        const void *addr = [[addrs objectAtIndex:i] pointerValue];
153                        if(dladdr(addr, &info))
154                                [mapping setObject:[NSString stringWithCString:info.dli_fname] forKey:[NSValue valueWithPointer:info.dli_fbase]];
155                        [ret appendFormat:@" 0x%X", addr];
156                }
157                NSEnumerator *mappingEnum = [mapping keyEnumerator];
158                NSValue *key = nil;
159                while((key = [mappingEnum nextObject]) != nil)
160                        [ret appendFormat:@"\n0x%X\t%@", [key pointerValue], [mapping objectForKey:key]];
161        }
162        NSLog(@"%@", ret);     
163}
164
165+ (NSString *) rootMenuLabel
166{
167        return (@"net.pmerrill.Sapphire" );
168}
169
170- (id) initWithScene: (BRRenderScene *) scene
171{
172        self = [super initWithScene:scene];
173       
174        //Setup the theme's scene
175        SapphireTheme *theme = [SapphireTheme sharedTheme];
176        [theme setScene:[self scene]];
177       
178        moc = [[NSManagedObjectContext alloc] init];
179        [moc setUndoManager:nil];
180        NSString *mopath = [[NSBundle bundleForClass:[self class]] pathForResource:@"Sapphire" ofType:@"mom"];
181        NSURL *mourl = [NSURL fileURLWithPath:mopath];
182        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:mourl];
183        NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
184        [moc setPersistentStoreCoordinator:coord];
185        [coord release];
186       
187        NSFileManager *fm = [NSFileManager defaultManager];
188        NSString *storeFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.sapphireData"];
189        BOOL exists = [fm fileExistsAtPath:storeFile];
190        NSURL *storeUrl = [NSURL fileURLWithPath:storeFile];
191        NSError *error = nil;
192        [coord addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];
193        if(!exists)
194        {
195                NSString *plistFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.plist"];
196                if([fm fileExistsAtPath:plistFile])
197                {
198                        [SapphireMetaDataSupport importPlist:[plistFile stringByDeletingLastPathComponent] intoContext:moc];
199                        [SapphireMetaDataSupport save:moc];
200                }
201        }
202       
203       
204        settings                                                                = [[SapphireSettings alloc] initWithScene:[self scene] settingsPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/settings.plist"] context:moc];
205        [self setListTitle:                                             BRLocalizedString(@"Main Menu", @"")];
206        [settings setListTitle:                                 BRLocalizedString(@" Settings", @"Settings Menu Item")] ;
207        [settings setListIcon:                                  [theme gem:GEAR_GEM_KEY]];
208        [[self list] setDatasource:self];
209        if([SapphireFrontRowCompat usingFrontRow] && ![SapphireFrontRowCompat usingTakeTwo])
210        {
211                NSString *myBundlePath = [[NSBundle bundleForClass:[self class]] bundlePath] ;
212                NSString *onlyPath = [myBundlePath stringByAppendingPathComponent:@"/Contents/Frameworks/LeopardOnly.framework"];
213                NSBundle *only = [NSBundle bundleWithPath:onlyPath];
214                Class onlyClass = [only principalClass];
215                leoOnly = [[onlyClass alloc] initWithContext:moc];
216        }
217        mountsOnly = NO;
218       
219        return self;
220}
221
222- (void)dealloc
223{
224        [leoOnly release];
225        [names release];
226        [controllers release];
227        [masterNames release];
228        [masterControllers release];
229        [moc release];
230        [SapphireSettings relinquishSettings];
231        [settings release];
232        [SapphireImportHelper relinquishHelper];
233        [super dealloc];
234}
235
236- (void)recreateMenu
237{
238        names = [[NSMutableArray alloc] init];
239        controllers = [[NSMutableArray alloc] init];
240        if(mountsOnly)
241        {
242                masterNames = [[NSArray alloc] init];
243                masterControllers = [[NSArray alloc] init];
244        }
245        else
246        {
247                SapphireImporterDataMenu *allImporter   = [self allImporter];
248                NSMutableArray *mutableMasterNames = [[NSMutableArray alloc] init];
249                NSMutableArray *mutableMasterControllers = [[NSMutableArray alloc] init];
250               
251                SapphireBrowser *tvBrowser = [self tvBrowser];
252                [mutableMasterNames addObject:BRLocalizedString(@"  TV Shows", nil)];
253                [mutableMasterControllers addObject:tvBrowser];
254               
255                SapphireBrowser *movieBrowser = [self movieBrowser];
256                [mutableMasterNames addObject:BRLocalizedString(@"  Movies", nil)];
257                [mutableMasterControllers addObject:movieBrowser];
258               
259                [mutableMasterNames addObjectsFromArray:[NSArray arrayWithObjects:
260                                                                                                 ALL_IMPORT_MENU_ITEM,
261                                                                                                 SETTINGS_MENU_ITEM,
262                                                                                                 RESET_MENU_ITEM,
263                                                                                                 nil]];
264                [mutableMasterControllers addObjectsFromArray:[NSArray arrayWithObjects:
265                                                                                                           allImporter,
266                                                                                                           settings,
267                                                                                                           nil]];
268                masterNames = [[NSArray alloc] initWithArray:mutableMasterNames];
269                masterControllers = [[NSArray alloc] initWithArray:mutableMasterControllers];
270                [mutableMasterNames release];
271                [mutableMasterControllers release];             
272        }
273        [self setMenuFromSettings];
274}
275
276- (SapphireBrowser *)tvBrowser
277{
278        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
279        SapphireEntityDirectory *tvDir = [[SapphireEntityDirectory alloc] initWithEntityName:SapphireTVShowName inContext:moc];
280        SapphireBrowser *tvBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:tvDir];
281        [tvDir release];
282        [tvBrowser setListTitle:BRLocalizedString(@" TV Shows", nil)];
283        [tvBrowser setListIcon:predicateGem];
284        return [tvBrowser autorelease];
285}
286
287- (SapphireBrowser *)movieBrowser
288{
289        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
290        SapphireMovieDirectory *movieDir = [[SapphireMovieDirectory alloc] initWithContext:moc];
291        SapphireBrowser *movieBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:movieDir];
292        [movieDir release];
293        [movieBrowser setListTitle:BRLocalizedString(@" Movies", nil)];
294        [movieBrowser setListIcon:predicateGem];
295        return [movieBrowser autorelease];     
296}
297
298- (void)setToMountsOnly
299{
300        [self setListTitle:BRLocalizedString(@"Collections", @"")];
301        mountsOnly = YES;
302}
303
304- (SapphireImporterDataMenu *)allImporter
305{
306        SapphireXMLFileDataImporter *xmlImpr = [[SapphireXMLFileDataImporter alloc] init];
307        SapphireFileDataImporter *fileImp = [[SapphireFileDataImporter alloc] init];
308        SapphireTVShowImporter *tvImp = [[SapphireTVShowImporter alloc] initWithContext:moc];
309        SapphireMovieImporter *movImp = [[SapphireMovieImporter alloc] initWithContext:moc];
310        SapphireAllImporter *allImp = [[SapphireAllImporter alloc] initWithImporters:[NSArray arrayWithObjects:xmlImpr,tvImp,movImp,fileImp,nil]];
311        [xmlImpr release];
312        [fileImp release];
313        [tvImp release];
314        [movImp release];
315        SapphireImporterDataMenu *ret = [[SapphireImporterDataMenu alloc] initWithScene:[self scene] context:moc importer:allImp];
316        [allImp release];
317        return [ret autorelease];
318}
319
320- (SapphireSettings *)settings
321{
322        return settings;
323}
324
325- (void)setMenuFromSettings
326{
327        [names removeAllObjects];
328        [controllers removeAllObjects];
329        [names addObjectsFromArray:masterNames];
330        [controllers addObjectsFromArray:masterControllers];
331        NSMutableDictionary *dvds = [NSMutableDictionary dictionary];
332        NSEnumerator *dvdEnum = [[NSClassFromString(@"BRDiskArbHandler") mountedDVDs] objectEnumerator];
333        BRDiskInfo *dvdInfo;
334        while((dvdInfo = [dvdEnum nextObject]) != nil)
335        {
336                NSString *mountpoint = [dvdInfo mountpoint];
337                [dvds setObject:dvdInfo forKey:mountpoint];
338        }
339       
340        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
341        NSEnumerator *browserPointsEnum = [[SapphireCollectionDirectory availableCollectionDirectoriesInContext:moc] objectEnumerator];
342        SapphireCollectionDirectory *browserPoint = nil;
343        int index = 2;
344        if(mountsOnly)
345                index = 0;
346        while((browserPoint = [browserPointsEnum nextObject]) != nil)
347        {
348                if([browserPoint hiddenValue])
349                        continue;
350                id controller = nil;
351                if((dvdInfo = [dvds objectForKey:browserPoint]) != nil)
352                {
353                        BRDVDMediaAsset *asset = [BRDVDMediaAsset assetFromDiskInfo:dvdInfo];
354                        controller = [[SapphireDVDLoadingController alloc] initWithScene:[self scene] forAsset:asset];
355                        [controller retain];
356                }
357                else
358                {
359                        SapphireDirectoryMetaData *meta = [browserPoint directory];
360                        controller = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:meta];
361                        [controller setListTitle:[NSString stringWithFormat:@" %@",[[meta path] lastPathComponent]]];
362                        [controller setListIcon:predicateGem];
363                }
364                if(controller != nil)
365                {
366                        [names insertObject:[NSString stringWithFormat:@"  %@", [[browserPoint directory] path]] atIndex:index];
367                        [controllers insertObject:controller atIndex:index];
368                        [controller release];
369                        index++;
370                }
371        }       
372       
373        if([settings disableUIQuit] || mountsOnly)
374                [names removeLastObject];
375}
376
377- (void) willBePushed
378{
379    // We're about to be placed on screen, but we're not yet there
380    [self recreateMenu];
381        [[self list] reload];
382    // always call super
383    [super willBePushed];
384}
385
386- (void) wasPushed
387{
388    // We've just been put on screen, the user can see this controller's content now
389   
390    // always call super
391    [super wasPushed];
392}
393
394- (void) willBePopped
395{
396    // The user pressed Menu, but we've not been removed from the screen yet
397   
398    // always call super
399    [super willBePopped];
400}
401
402- (void) wasPopped
403{
404    // The user pressed Menu, removing us from the screen
405   
406    // always call super
407    [super wasPopped];
408}
409
410- (void) willBeBuried
411{
412    // The user just chose an option, and we will be taken off the screen
413   
414    // always call super
415    [super willBeBuried];
416}
417
418- (void) wasBuriedByPushingController: (BRLayerController *) controller
419{
420    // The user chose an option and this controller os no longer on screen
421   
422    // always call super
423    [super wasBuriedByPushingController: controller];
424}
425
426- (void) willBeExhumed
427{
428    // the user pressed Menu, but we've not been revealed yet
429   
430    // always call super
431    [super willBeExhumed];
432        [self setMenuFromSettings];
433        [[self list] reload];
434        [SapphireFrontRowCompat renderScene:[self scene]];
435}
436
437- (void) wasExhumedByPoppingController: (BRLayerController *) controller
438{
439    // handle being revealed when the user presses Menu
440   
441    // always call super
442    [super wasExhumedByPoppingController: controller];
443}
444
445- (long) itemCount
446{
447    // return the number of items in your menu list here
448        return ( [ names count]);
449}
450
451- (id<BRMenuItemLayer>) itemForRow: (long) row
452{
453/*
454    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
455    // return that object, it will be used to display the list item.
456*/
457        if( row > [names count] ) return ( nil ) ;
458       
459        BRAdornedMenuItemLayer * result = nil ;
460        NSString *name = [names objectAtIndex:row];
461        result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:YES];
462       
463        SapphireTheme *theme = [SapphireTheme sharedTheme];
464        if([name isEqual: ALL_IMPORT_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:IMPORT_GEM_KEY] forMenu:result];
465        else if([name isEqual: SETTINGS_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:GEAR_GEM_KEY] forMenu:result];
466        else if([name isEqual: RESET_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:FRONTROW_GEM_KEY] forMenu:result];
467        else if([name isEqual: @"  TV Shows"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:TV_GEM_KEY] forMenu:result];
468        else if([name isEqual: @"  Movies"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:MOV_GEM_KEY] forMenu:result];
469        else [SapphireFrontRowCompat setLeftIcon:[SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]] forMenu:result];
470       
471        // add text
472        [SapphireFrontRowCompat setTitle:name forMenu:result];
473                               
474        return ( result ) ;
475}
476
477- (NSString *) titleForRow: (long) row
478{
479
480        if ( row > [ names count] ) return ( nil );
481       
482        NSString *result = [ names objectAtIndex: row] ;
483        return ( result ) ;
484/*
485    // return the title for the list item at the given index here
486    return ( @"Sapphire" );
487*/
488}
489
490- (long) rowForTitle: (NSString *) title
491{
492    long result = -1;
493    long i, count = [self itemCount];
494    for ( i = 0; i < count; i++ )
495    {
496        if ( [title isEqualToString: [self titleForRow: i]] )
497        {
498            result = i;
499            break;
500        }
501    }
502   
503    return ( result );
504}
505
506- (void) itemSelected: (long) row
507{
508    // This is called when the user presses play/pause on a list item
509        if(row == [controllers count])
510                [[NSApplication sharedApplication] terminate:self];
511        id controller = [controllers objectAtIndex:row];
512       
513        // This if statement needs to be done in a much more elegant way
514        [[self stack] pushController:controller];
515}
516
517- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
518{
519    // If subclassing BRMediaMenuController, this function is called when the selection cursor
520    // passes over an item.
521    return ( nil );
522}
523
524@end
Note: See TracBrowser for help on using the repository browser.