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

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

Upgrading metadata isn't done when finder starts anymore

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        NSFileManager *fm = [NSFileManager defaultManager];
179        NSString *storeFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.sapphireData"];
180        BOOL exists = [fm fileExistsAtPath:storeFile];
181        NSString *plistFile = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/metaData.plist"];
182        BOOL oldExists = [fm fileExistsAtPath:plistFile];
183        if(!exists && oldExists)
184        {
185                NSLog(@"Detected upgrade needed");
186                needsUpgrade = YES;
187                return self;
188        }
189        moc = [[NSManagedObjectContext alloc] init];
190        [moc setUndoManager:nil];
191        NSString *mopath = [[NSBundle bundleForClass:[self class]] pathForResource:@"Sapphire" ofType:@"mom"];
192        NSURL *mourl = [NSURL fileURLWithPath:mopath];
193        NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:mourl];
194        NSPersistentStoreCoordinator *coord = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
195        [moc setPersistentStoreCoordinator:coord];
196        [coord release];
197       
198        NSURL *storeUrl = [NSURL fileURLWithPath:storeFile];
199        NSError *error = nil;
200        [coord addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error];   
201       
202        settings                                                                = [[SapphireSettings alloc] initWithScene:[self scene] settingsPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Library/Application Support/Sapphire/settings.plist"] context:moc];
203        [self setListTitle:                                             BRLocalizedString(@"Main Menu", @"")];
204        [settings setListTitle:                                 BRLocalizedString(@" Settings", @"Settings Menu Item")] ;
205        [settings setListIcon:                                  [theme gem:GEAR_GEM_KEY]];
206        [[self list] setDatasource:self];
207        if([SapphireFrontRowCompat usingFrontRow] && ![SapphireFrontRowCompat usingTakeTwo])
208        {
209                NSString *myBundlePath = [[NSBundle bundleForClass:[self class]] bundlePath] ;
210                NSString *onlyPath = [myBundlePath stringByAppendingPathComponent:@"/Contents/Frameworks/LeopardOnly.framework"];
211                NSBundle *only = [NSBundle bundleWithPath:onlyPath];
212                Class onlyClass = [only principalClass];
213                leoOnly = [[onlyClass alloc] initWithContext:moc];
214        }
215        mountsOnly = NO;
216       
217        return self;
218}
219
220- (void)dealloc
221{
222        [leoOnly release];
223        [names release];
224        [controllers release];
225        [masterNames release];
226        [masterControllers release];
227        [moc release];
228        [SapphireSettings relinquishSettings];
229        [settings release];
230        [SapphireImportHelper relinquishHelper];
231        [super dealloc];
232}
233
234- (void)recreateMenu
235{
236        names = [[NSMutableArray alloc] init];
237        controllers = [[NSMutableArray alloc] init];
238        if(mountsOnly)
239        {
240                masterNames = [[NSArray alloc] init];
241                masterControllers = [[NSArray alloc] init];
242        }
243        else
244        {
245                SapphireImporterDataMenu *allImporter   = [self allImporter];
246                NSMutableArray *mutableMasterNames = [[NSMutableArray alloc] init];
247                NSMutableArray *mutableMasterControllers = [[NSMutableArray alloc] init];
248               
249                SapphireBrowser *tvBrowser = [self tvBrowser];
250                [mutableMasterNames addObject:BRLocalizedString(@"  TV Shows", nil)];
251                [mutableMasterControllers addObject:tvBrowser];
252               
253                SapphireBrowser *movieBrowser = [self movieBrowser];
254                [mutableMasterNames addObject:BRLocalizedString(@"  Movies", nil)];
255                [mutableMasterControllers addObject:movieBrowser];
256               
257                [mutableMasterNames addObjectsFromArray:[NSArray arrayWithObjects:
258                                                                                                 ALL_IMPORT_MENU_ITEM,
259                                                                                                 SETTINGS_MENU_ITEM,
260                                                                                                 RESET_MENU_ITEM,
261                                                                                                 nil]];
262                [mutableMasterControllers addObjectsFromArray:[NSArray arrayWithObjects:
263                                                                                                           allImporter,
264                                                                                                           settings,
265                                                                                                           nil]];
266                masterNames = [[NSArray alloc] initWithArray:mutableMasterNames];
267                masterControllers = [[NSArray alloc] initWithArray:mutableMasterControllers];
268                [mutableMasterNames release];
269                [mutableMasterControllers release];             
270        }
271        [self setMenuFromSettings];
272}
273
274- (SapphireBrowser *)tvBrowser
275{
276        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
277        SapphireEntityDirectory *tvDir = [[SapphireEntityDirectory alloc] initWithEntityName:SapphireTVShowName inContext:moc];
278        SapphireBrowser *tvBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:tvDir];
279        [tvDir release];
280        [tvBrowser setListTitle:BRLocalizedString(@" TV Shows", nil)];
281        [tvBrowser setListIcon:predicateGem];
282        return [tvBrowser autorelease];
283}
284
285- (SapphireBrowser *)movieBrowser
286{
287        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
288        SapphireMovieDirectory *movieDir = [[SapphireMovieDirectory alloc] initWithContext:moc];
289        SapphireBrowser *movieBrowser = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:movieDir];
290        [movieDir release];
291        [movieBrowser setListTitle:BRLocalizedString(@" Movies", nil)];
292        [movieBrowser setListIcon:predicateGem];
293        return [movieBrowser autorelease];     
294}
295
296- (void)setToMountsOnly
297{
298        [self setListTitle:BRLocalizedString(@"Collections", @"")];
299        mountsOnly = YES;
300}
301
302- (SapphireImporterDataMenu *)allImporter
303{
304        SapphireXMLFileDataImporter *xmlImpr = [[SapphireXMLFileDataImporter alloc] init];
305        SapphireFileDataImporter *fileImp = [[SapphireFileDataImporter alloc] init];
306        SapphireTVShowImporter *tvImp = [[SapphireTVShowImporter alloc] initWithContext:moc];
307        SapphireMovieImporter *movImp = [[SapphireMovieImporter alloc] initWithContext:moc];
308        SapphireAllImporter *allImp = [[SapphireAllImporter alloc] initWithImporters:[NSArray arrayWithObjects:xmlImpr,tvImp,movImp,fileImp,nil]];
309        [xmlImpr release];
310        [fileImp release];
311        [tvImp release];
312        [movImp release];
313        SapphireImporterDataMenu *ret = [[SapphireImporterDataMenu alloc] initWithScene:[self scene] context:moc importer:allImp];
314        [allImp release];
315        return [ret autorelease];
316}
317
318- (SapphireSettings *)settings
319{
320        return settings;
321}
322
323- (BOOL)upgradeNeeded
324{
325        return needsUpgrade;
326}
327
328- (void)setMenuFromSettings
329{
330        [names removeAllObjects];
331        [controllers removeAllObjects];
332        [names addObjectsFromArray:masterNames];
333        [controllers addObjectsFromArray:masterControllers];
334        NSMutableDictionary *dvds = [NSMutableDictionary dictionary];
335        NSEnumerator *dvdEnum = [[NSClassFromString(@"BRDiskArbHandler") mountedDVDs] objectEnumerator];
336        BRDiskInfo *dvdInfo;
337        while((dvdInfo = [dvdEnum nextObject]) != nil)
338        {
339                NSString *mountpoint = [dvdInfo mountpoint];
340                [dvds setObject:dvdInfo forKey:mountpoint];
341        }
342       
343        BRTexture *predicateGem = [SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]];
344        NSEnumerator *browserPointsEnum = [[SapphireCollectionDirectory availableCollectionDirectoriesInContext:moc] objectEnumerator];
345        SapphireCollectionDirectory *browserPoint = nil;
346        int index = 2;
347        if(mountsOnly)
348                index = 0;
349        while((browserPoint = [browserPointsEnum nextObject]) != nil)
350        {
351                if([browserPoint hiddenValue])
352                        continue;
353                id controller = nil;
354                if((dvdInfo = [dvds objectForKey:browserPoint]) != nil)
355                {
356                        BRDVDMediaAsset *asset = [BRDVDMediaAsset assetFromDiskInfo:dvdInfo];
357                        controller = [[SapphireDVDLoadingController alloc] initWithScene:[self scene] forAsset:asset];
358                        [controller retain];
359                }
360                else
361                {
362                        SapphireDirectoryMetaData *meta = [browserPoint directory];
363                        controller = [[SapphireBrowser alloc] initWithScene:[self scene] metaData:meta];
364                        [controller setListTitle:[NSString stringWithFormat:@" %@",[[meta path] lastPathComponent]]];
365                        [controller setListIcon:predicateGem];
366                }
367                if(controller != nil)
368                {
369                        [names insertObject:[NSString stringWithFormat:@"  %@", [[browserPoint directory] path]] atIndex:index];
370                        [controllers insertObject:controller atIndex:index];
371                        [controller release];
372                        index++;
373                }
374        }       
375       
376        if([settings disableUIQuit] || mountsOnly)
377                [names removeLastObject];
378}
379
380- (void) willBePushed
381{
382    // We're about to be placed on screen, but we're not yet there
383    [self recreateMenu];
384        [[self list] reload];
385    // always call super
386    [super willBePushed];
387}
388
389- (void) wasPushed
390{
391    // We've just been put on screen, the user can see this controller's content now
392   
393    // always call super
394    [super wasPushed];
395}
396
397- (void) willBePopped
398{
399    // The user pressed Menu, but we've not been removed from the screen yet
400   
401    // always call super
402    [super willBePopped];
403}
404
405- (void) wasPopped
406{
407    // The user pressed Menu, removing us from the screen
408   
409    // always call super
410    [super wasPopped];
411}
412
413- (void) willBeBuried
414{
415    // The user just chose an option, and we will be taken off the screen
416   
417    // always call super
418    [super willBeBuried];
419}
420
421- (void) wasBuriedByPushingController: (BRLayerController *) controller
422{
423    // The user chose an option and this controller os no longer on screen
424   
425    // always call super
426    [super wasBuriedByPushingController: controller];
427}
428
429- (void) willBeExhumed
430{
431    // the user pressed Menu, but we've not been revealed yet
432   
433    // always call super
434    [super willBeExhumed];
435        [self setMenuFromSettings];
436        [[self list] reload];
437        [SapphireFrontRowCompat renderScene:[self scene]];
438}
439
440- (void) wasExhumedByPoppingController: (BRLayerController *) controller
441{
442    // handle being revealed when the user presses Menu
443   
444    // always call super
445    [super wasExhumedByPoppingController: controller];
446}
447
448- (long) itemCount
449{
450    // return the number of items in your menu list here
451        return ( [ names count]);
452}
453
454- (id<BRMenuItemLayer>) itemForRow: (long) row
455{
456/*
457    // build a BRTextMenuItemLayer or a BRAdornedMenuItemLayer, etc. here
458    // return that object, it will be used to display the list item.
459*/
460        if( row > [names count] ) return ( nil ) ;
461       
462        BRAdornedMenuItemLayer * result = nil ;
463        NSString *name = [names objectAtIndex:row];
464        result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:YES];
465       
466        SapphireTheme *theme = [SapphireTheme sharedTheme];
467        if([name isEqual: ALL_IMPORT_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:IMPORT_GEM_KEY] forMenu:result];
468        else if([name isEqual: SETTINGS_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:GEAR_GEM_KEY] forMenu:result];
469        else if([name isEqual: RESET_MENU_ITEM]) [SapphireFrontRowCompat setLeftIcon:[theme gem:FRONTROW_GEM_KEY] forMenu:result];
470        else if([name isEqual: @"  TV Shows"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:TV_GEM_KEY] forMenu:result];
471        else if([name isEqual: @"  Movies"]) [SapphireFrontRowCompat setLeftIcon:[theme gem:MOV_GEM_KEY] forMenu:result];
472        else [SapphireFrontRowCompat setLeftIcon:[SapphireApplianceController gemForPredicate:[SapphireApplianceController predicate]] forMenu:result];
473       
474        // add text
475        [SapphireFrontRowCompat setTitle:name forMenu:result];
476                               
477        return ( result ) ;
478}
479
480- (NSString *) titleForRow: (long) row
481{
482
483        if ( row > [ names count] ) return ( nil );
484       
485        NSString *result = [ names objectAtIndex: row] ;
486        return ( result ) ;
487/*
488    // return the title for the list item at the given index here
489    return ( @"Sapphire" );
490*/
491}
492
493- (long) rowForTitle: (NSString *) title
494{
495    long result = -1;
496    long i, count = [self itemCount];
497    for ( i = 0; i < count; i++ )
498    {
499        if ( [title isEqualToString: [self titleForRow: i]] )
500        {
501            result = i;
502            break;
503        }
504    }
505   
506    return ( result );
507}
508
509- (void) itemSelected: (long) row
510{
511    // This is called when the user presses play/pause on a list item
512        if(row == [controllers count])
513                [[NSApplication sharedApplication] terminate:self];
514        id controller = [controllers objectAtIndex:row];
515       
516        // This if statement needs to be done in a much more elegant way
517        [[self stack] pushController:controller];
518}
519
520- (id<BRMediaPreviewController>) previewControllerForItem: (long) item
521{
522    // If subclassing BRMediaMenuController, this function is called when the selection cursor
523    // passes over an item.
524    return ( nil );
525}
526
527@end
Note: See TracBrowser for help on using the repository browser.