source: branches/CoreData/SapphireFrappliance/MetaDataImporting/SapphirePosterChooser.m @ 899

Revision 899, 14.9 KB checked in by gbooker, 5 years ago (diff)

Switch to the compatible method for updating the preview and added a case where the update should be done.

Line 
1/*
2 * SapphirePosterChooser.m
3 * Sapphire
4 *
5 * Created by Patrick Merrill on Oct. 11, 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 "SapphirePosterChooser.h"
22#import "SapphireFileMetaData.h"
23#import "SapphireSettings.h"
24#import "SapphireMediaPreview.h"
25#import "SapphireMedia.h"
26#import "SapphireMetaData.h"
27#import "SapphireWaitDisplay.h"
28#import "SapphireDirectoryMetaData.h"
29#import <SapphireCompatClasses/SapphireFrontRowCompat.h>
30#import "SapphireApplianceController.h"
31
32#import "NSImage-Extensions.h"
33
34NSData *CreateBitmapDataFromImage(CGImageRef image, unsigned int width, unsigned int height);
35
36@interface BRListControl (definedin1_1)
37- (double)renderSelection;
38@end
39
40@interface SapphirePosterChooser (private)
41- (BRBlurryImageLayer *) getPosterLayer: (NSString *) thePosterPath;
42- (void) loadPoster:(int)index;
43- (void) hideIconMarch;
44- (void) showIconMarch;
45- (void) selectionChanged: (NSNotification *) note;
46@end
47
48@implementation SapphirePosterChooser
49
50- (id) initWithScene: (BRRenderScene *) scene
51{
52        self = [super initWithScene: scene];
53        if(!self)
54                return nil;
55        selectedPoster = -1;
56       
57        // we want to know when the list selection changes, so we can pass
58    // that information on to the icon march layer
59    [[NSNotificationCenter defaultCenter] addObserver: self
60                                             selector: @selector(selectionChanged:)
61                                                 name: @"ListControlSelectionChangedNotification"
62                                               object: [self list]];
63       
64        /* Set a control to display the fileName */
65        fileInfoText = [SapphireFrontRowCompat newTextControlWithScene:scene];
66        [SapphireFrontRowCompat setText:@"No File" withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
67        NSRect frame = [SapphireFrontRowCompat frameOfController:self];
68        frame.origin.y = frame.size.height / 1.25f;
69        frame.origin.x = (frame.size.width / 4.0f) ;
70        defaultImage = [[self getPosterLayer:[[NSBundle bundleForClass:[self class]] pathForResource:@"PH" ofType:@"png"]] retain];
71
72       
73        [fileInfoText setFrame: frame];
74        [self addControl: fileInfoText];
75       
76        /* Setup posterMarch controls */
77        posterMarch = [SapphireFrontRowCompat newMarchingIconLayerWithScene:scene];
78        [SapphireLayoutManager setCustomLayoutOnControl:self];
79       
80        return self;
81}
82
83- (void)dealloc
84{
85        [[NSNotificationCenter defaultCenter] removeObserver: self];
86    [posterMarch removeFromSuperlayer];
87//    [posterMarch setIconSource: nil];  //This throws an exception
88        [posters release];
89        [posterLayers release];
90        [fileName release];
91        [movieTitle release];
92        [fileInfoText release];
93        [posterMarch release];
94        [defaultImage release];
95        [meta release];
96        [super dealloc];
97}
98
99- (void)setRefreshInvokation: (NSInvocation *)invoke;
100{
101        [refreshInvoke release];
102        refreshInvoke = [invoke retain];
103}
104
105- (void) resetLayout
106{
107    [super resetLayout];
108        [SapphireFrontRowCompat renderScene:[self scene]];
109}
110
111- (void) willBePushed
112{
113        [self showIconMarch];
114    // always call super
115    [super willBePushed];
116}
117
118- (void)doMyLayout
119{
120        NSRect master = [SapphireFrontRowCompat frameOfController:self];
121        NSSize txtSize = [SapphireFrontRowCompat textControl:fileInfoText renderedSizeWithMaxSize:NSMakeSize(master.size.width * 2.0f/3.0f, master.size.height * 0.4f)];
122        NSRect frame;
123        frame.origin.x = (master.size.width - txtSize.width) * 0.5f;
124        frame.origin.y = (master.size.height * 0.44f - txtSize.height) + master.size.height * 0.3f/0.8f + master.origin.y;
125        frame.size = txtSize;
126        [fileInfoText setFrame:frame];
127}
128
129- (void)wasPushed
130{
131        [self doMyLayout];
132        [[self list] reload];
133        [super wasPushed];
134}
135
136- (void) wasPopped
137{
138    // The user pressed Menu, removing us from the screen
139    // always call super
140    [super wasPopped];
141    // remove the icon march from the scene
142    [self hideIconMarch];
143}
144
145/*!
146 * @brief Override the layout
147 *
148 */
149- (NSRect)listRectWithSize:(NSRect)listFrame inMaster:(NSRect)master
150{
151        listFrame.size.height -= 2.5f*listFrame.origin.y;
152        listFrame.size.width*= 0.45f;
153        listFrame.origin.x = (master.size.width - listFrame.size.width) * 0.85f;
154        listFrame.origin.y = (master.size.height * 0.3f - listFrame.size.height) + master.size.height * 0.3f/0.8f + master.origin.y;
155        return listFrame;
156}
157
158- (BRLayerController *)doRefresh
159{
160        [refreshInvoke invoke];
161        BRLayerController *ret = nil;
162        [refreshInvoke getReturnValue:&ret];
163        return ret;
164}
165
166- (void) itemSelected: (long) row
167{
168        /*User made a selection*/
169        if ( refreshInvoke != nil && row == [posters count] )
170        {
171                NSInvocation *invoke = [NSInvocation invocationWithMethodSignature: [self methodSignatureForSelector: @selector(doRefresh)]];
172                [invoke setSelector: @selector(doRefresh)];
173                [invoke setTarget:   self];
174               
175                SapphireWaitDisplay *wait = [[SapphireWaitDisplay alloc] initWithScene: [self scene]
176                                                                                                                                                 title: BRLocalizedString(@"Getting artwork selection", @"Getting artwork selection")
177                                                                                                                                        invokation: invoke];
178                [[self stack] swapController:[wait autorelease]];
179        }
180        else
181        {
182                selectedPoster = row;
183                if ( [[posters objectAtIndex:selectedPoster] isKindOfClass:[NSImage class]] )
184                        [[posters objectAtIndex:row] writeToFile:[meta coverArtPath] atomically:YES];
185                [[self stack] popController];
186        }
187}
188
189- (BOOL)okayToDisplay
190{
191        if([[self list] respondsToSelector:@selector(renderSelection)] || [SapphireFrontRowCompat usingLeopardOrATypeOfTakeTwo])
192                return [[SapphireSettings sharedSettings] displayPosterChooser];
193        else
194                return NO;
195}
196
197- (NSArray *)posters
198{
199        return posters;
200}
201
202- (void)setPosters:(NSArray *)posterList
203{
204        posters = [posterList retain];
205        if([posters count] > 5)
206        {
207                [posterMarch release];
208                posterMarch = nil;
209        }
210        [self loadPosters];
211    [posterMarch setIconSource: self];
212        [[self list] setDatasource:self];
213}
214
215- (void)setPosterImages:(NSArray *)posterList
216{
217        posters = [posterList retain];
218
219        [posterMarch release];
220        posterMarch = nil;
221
222        [[self list] setDatasource: self];
223}
224
225- (void)loadPosters
226{
227        int i, count = [posters count];
228        posterLayers = [posters mutableCopy];
229        for(i=0; i<count; i++)
230                [self loadPoster:i];
231        [posterMarch reload] ;
232        [SapphireFrontRowCompat renderScene:[self scene]];
233}
234
235- (void)reloadPoster:(int)index
236{
237        [self loadPoster:index];
238        [posterMarch _updateIcons];
239        [self resetPreviewController];
240        [SapphireFrontRowCompat renderScene:[self scene]];
241}
242
243- (void)setFileName:(NSString*)choosingForFileName
244{
245        fileName=[choosingForFileName retain];
246        if(movieTitle)
247                [SapphireFrontRowCompat setText:[NSString stringWithFormat:@"%@ (%@)",movieTitle,fileName] withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
248        else
249                [SapphireFrontRowCompat setText:fileName withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
250}
251
252- (void)setFile:(SapphireFileMetaData *)aMeta;
253{
254        [meta release];
255        meta = [aMeta retain];
256}
257
258- (NSString *)fileName
259{
260        return fileName;
261}
262
263- (void)setMovieTitle:(NSString *)theMovieTitle
264{
265        movieTitle = [theMovieTitle retain];
266        if(fileName)
267                [SapphireFrontRowCompat setText:[NSString stringWithFormat:@"%@ (%@)",movieTitle,fileName] withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
268        else
269                [SapphireFrontRowCompat setText:movieTitle withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
270       
271        NSRect master = [SapphireFrontRowCompat frameOfController:self];
272        NSSize txtSize = [SapphireFrontRowCompat textControl:fileInfoText renderedSizeWithMaxSize:NSMakeSize(master.size.width * 2.0f/3.0f, master.size.height * 0.4f)];
273        NSRect frame;
274        frame.origin.x = (master.size.width - txtSize.width) * 0.5f;
275        frame.origin.y = (master.size.height * 0.44f - txtSize.height) + master.size.height * 0.3f/0.8f + master.origin.y;
276        frame.size = txtSize;
277        [fileInfoText setFrame:frame];
278}
279
280- (NSString *)movieTitle
281{
282        return movieTitle;
283}
284
285- (long)selectedPoster
286{
287        return selectedPoster;
288}
289
290- (long) iconCount
291{
292        return [posterLayers count];
293}
294
295- (NSDictionary *) iconInfoAtIndex: (long) index
296{
297        return [NSDictionary dictionaryWithObject:[posterLayers objectAtIndex:index] forKey:@"icon"];
298}
299
300- (id) iconAtIndex: (long) index
301{
302    if ( index >= [posterLayers count] )
303        return nil;
304       
305    return [posterLayers objectAtIndex:index];
306}
307
308
309- (long) itemCount
310{
311        if ( refreshInvoke != nil )
312                return [posters count] + 1;
313       
314        return [posters count];
315}
316
317
318- (id) itemForRow: (long) row
319{
320        BRAdornedMenuItemLayer *result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:NO];
321        if ( refreshInvoke != nil && row == [posters count] )
322                [SapphireFrontRowCompat setTitle:BRLocalizedString(@"Refresh", @"Reload images") forMenu:result];
323        else
324                [SapphireFrontRowCompat setTitle:[NSString stringWithFormat:@"Version %2d",row+1] forMenu:result];
325        return result;
326}
327
328- (NSString *) titleForRow: (long) row
329{
330        if(row > [posters count])
331                return nil;
332
333        if (refreshInvoke != nil && row == [posters count])
334                return BRLocalizedString(@"Refresh", @"Reload images");
335
336        return [NSString stringWithFormat:@"Version %2d",row+1];
337}
338
339- (long) rowForTitle: (NSString *) title
340{
341    long result = -1;
342    long i, count = [self itemCount];
343    for ( i = 0; i < count; i++ )
344    {
345        if ( [title isEqualToString: [self titleForRow: i]] )
346       {
347            result = i;
348            break;
349       }
350    }
351    return ( result );
352}
353
354/*!
355 * @brief load poster image layers
356 *
357 * @param The index of the poster to load
358 */
359- (void) loadPoster:(int)index;
360{
361        NSString *poster = [posters objectAtIndex:index];
362        NSString *posterDest=[NSString stringWithFormat:@"%@/%@",
363                [applicationSupportDir() stringByAppendingPathComponent:@"Poster_Buffer"],
364                [poster lastPathComponent]];
365        [posterLayers replaceObjectAtIndex:index withObject:[self getPosterLayer:posterDest]];
366}
367
368- (BRBlurryImageLayer *) getPosterLayer: (NSString *) thePosterPath
369{
370        if([SapphireFrontRowCompat usingLeopardOrATypeOfTakeTwo])
371        {
372                /*The marching icons has changed, dramatically, so we do the changes here*/
373                id ret = [SapphireFrontRowCompat imageAtPath:thePosterPath];
374                if(ret != nil)
375                        return ret;
376                else
377                        return defaultImage;
378        }
379    NSURL * posterURL = [NSURL fileURLWithPath: thePosterPath];
380       
381    if (posterURL==nil)
382                return nil;
383        CGImageRef posterImage=NULL;
384        CGImageSourceRef  sourceRef;   
385    sourceRef = CGImageSourceCreateWithURL((CFURLRef)posterURL, NULL);
386    if(sourceRef) {
387        posterImage = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
388        CFRelease(sourceRef);
389    }
390    if(posterImage==nil)
391                return defaultImage;
392       
393    struct BRBitmapDataInfo info;
394    info.internalFormat = GL_RGBA;
395    info.dataFormat = GL_BGRA;
396    info.dataType = GL_UNSIGNED_INT_8_8_8_8_REV;
397    info.width = 510;
398    info.height = 755;
399       
400    BRRenderContext * context = [[self scene] resourceContext];
401               
402    NSData * data = CreateBitmapDataFromImage(posterImage,info.width,info.height );
403    BRBitmapTexture * lucid = [[BRBitmapTexture alloc] initWithBitmapData: data
404                                                                                                                           bitmapInfo: &info
405                                                                                                                                  context: context
406                                                                                                                                   mipmap: YES];
407    [data release];
408       
409    BRBitmapTexture * blur = [BRBlurryImageLayer blurredImageForImage: posterImage
410                                                            inContext: context
411                                                                 size: NSMakeSize(510.0f, 755.0f)];
412       
413    CFRelease( posterImage );
414       
415    BRBlurryImageLayer * result = [BRBlurryImageLayer layerWithScene: [self scene]];
416       
417    [result setLucidImage: lucid withReflection: nil];
418    [result setBlurryImage: blur withReflection: nil];
419       
420    [lucid release];
421       
422    return ( result );
423}
424
425- (void) hideIconMarch
426{
427        /* Might want to free memory here since posters won't be chosen again */
428    [posterMarch removeFromSuperlayer];
429}
430
431- (void) showIconMarch
432{
433        NSRect frame = [SapphireFrontRowCompat frameOfController:self];
434    frame.size.width *= 0.50f;
435        if(![SapphireFrontRowCompat usingLeopardOrATypeOfTakeTwo])
436        {
437                frame.size.height *= 1.7f;
438                frame.origin.y=-200.0f;
439        }
440        else
441                frame.size.height = ([fileInfoText frame].origin.y - frame.origin.y) * 1.2f;
442    [posterMarch setFrame: frame];
443        if(posterMarch != nil)
444                [SapphireFrontRowCompat addSublayer:posterMarch toControl:self];
445}
446
447- (void)setSelectionForPoster:(double)sel
448{
449        if(posterMarch == nil)
450                return;
451        NSMethodSignature *signature = [posterMarch methodSignatureForSelector:@selector(setSelection:)];
452        NSInvocation *selInv = [NSInvocation invocationWithMethodSignature:signature];
453        [selInv setSelector:@selector(setSelection:)];
454        if(strcmp([signature getArgumentTypeAtIndex:2], "l"))
455        {
456                double dvalue = sel;
457                [selInv setArgument:&dvalue atIndex:2];
458        }
459        else
460        {
461                long lvalue = sel;
462                [selInv setArgument:&lvalue atIndex:2];
463        }
464        [selInv invokeWithTarget:posterMarch];
465}
466
467- (void) selectionChanged: (NSNotification *) note
468{
469        /* ATV version 1.1 */
470        if([(BRListControl *)[note object] respondsToSelector:@selector(renderSelection)])
471                [self setSelectionForPoster:[(BRListControl *)[note object] renderSelection]];
472        /* ATV version 1.0 */
473        else
474                [self setSelectionForPoster:[(BRListControl *)[note object] selection]];
475}
476
477- (id<BRMediaPreviewController>) previewControlForItem: (long) row
478{
479        if(posterMarch != nil)
480                return nil;
481
482        SapphireMediaPreview *preview = [[SapphireMediaPreview alloc] initWithScene:[self scene]];
483        [preview setShowsMetadataImmediately:YES];
484       
485        if ( row < [posters count] )
486        {
487                [preview setMetaData:meta inMetaData:[meta parent]];
488               
489                SapphireMedia *asset = [[SapphireMedia alloc] initWithMediaURL:[NSURL fileURLWithPath:@"none"]];
490                id poster = [posters objectAtIndex:row];
491
492                if ( [poster isKindOfClass:[NSString class]] )
493                {
494                        NSString *posterDest = [NSString stringWithFormat:@"%@/%@",     [applicationSupportDir() stringByAppendingPathComponent:@"Poster_Buffer"],
495                                                                                                                                                [poster lastPathComponent]];
496                        [asset setImagePath: posterDest];
497                }
498                else
499                {
500                        [asset setImage: poster];
501                }
502
503                [preview setAsset:asset];
504                [asset release];
505        }
506        else if ( row == [posters count] )
507        {
508                NSMutableDictionary *refreshMeta = [NSMutableDictionary dictionary];
509                [refreshMeta setObject: BRLocalizedString( @"Refresh the artwork selection", @"Refresh the artwork selection" ) forKey: META_TITLE_KEY];
510                [preview setUtilityData: refreshMeta];
511        }
512
513        return [preview autorelease];
514}
515
516- (id<BRMediaPreviewController>) previewControllerForItem: (long) row
517{
518        return [self previewControlForItem:row];
519}
520
521
522@end
Note: See TracBrowser for help on using the repository browser.