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

Revision 827, 14.8 KB checked in by gbooker, 6 years ago (diff)

Added screen capture ability thanks to patch by wazza. Does not work on ATV since ATV is broken.
Fixes #45

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];
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 usingFrontRow])
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        [SapphireFrontRowCompat renderScene:[self scene]];
240}
241
242- (void)setFileName:(NSString*)choosingForFileName
243{
244        fileName=[choosingForFileName retain];
245        if(movieTitle)
246                [SapphireFrontRowCompat setText:[NSString stringWithFormat:@"%@ (%@)",movieTitle,fileName] withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
247        else
248                [SapphireFrontRowCompat setText:fileName withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
249}
250
251- (void)setFile:(SapphireFileMetaData *)aMeta;
252{
253        [meta release];
254        meta = [aMeta retain];
255}
256
257- (NSString *)fileName
258{
259        return fileName;
260}
261
262- (void)setMovieTitle:(NSString *)theMovieTitle
263{
264        movieTitle = [theMovieTitle retain];
265        if(fileName)
266                [SapphireFrontRowCompat setText:[NSString stringWithFormat:@"%@ (%@)",movieTitle,fileName] withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
267        else
268                [SapphireFrontRowCompat setText:movieTitle withAtrributes:[[BRThemeInfo sharedTheme] paragraphTextAttributes] forControl:fileInfoText];
269       
270        NSRect master = [SapphireFrontRowCompat frameOfController:self];
271        NSSize txtSize = [SapphireFrontRowCompat textControl:fileInfoText renderedSizeWithMaxSize:NSMakeSize(master.size.width * 2.0f/3.0f, master.size.height * 0.4f)];
272        NSRect frame;
273        frame.origin.x = (master.size.width - txtSize.width) * 0.5f;
274        frame.origin.y = (master.size.height * 0.44f - txtSize.height) + master.size.height * 0.3f/0.8f + master.origin.y;
275        frame.size = txtSize;
276        [fileInfoText setFrame:frame];
277}
278
279- (NSString *)movieTitle
280{
281        return movieTitle;
282}
283
284- (long)selectedPoster
285{
286        return selectedPoster;
287}
288
289- (long) iconCount
290{
291        return [posterLayers count];
292}
293
294- (NSDictionary *) iconInfoAtIndex: (long) index
295{
296        return [NSDictionary dictionaryWithObject:[posterLayers objectAtIndex:index] forKey:@"icon"];
297}
298
299- (id) iconAtIndex: (long) index
300{
301    if ( index >= [posterLayers count] )
302        return nil;
303       
304    return [posterLayers objectAtIndex:index];
305}
306
307
308- (long) itemCount
309{
310        if ( refreshInvoke != nil )
311                return [posters count] + 1;
312       
313        return [posters count];
314}
315
316
317- (id) itemForRow: (long) row
318{
319        BRAdornedMenuItemLayer *result = [SapphireFrontRowCompat textMenuItemForScene:[self scene] folder:NO];
320        if ( refreshInvoke != nil && row == [posters count] )
321                [SapphireFrontRowCompat setTitle:BRLocalizedString(@"Refresh", @"Reload images") forMenu:result];
322        else
323                [SapphireFrontRowCompat setTitle:[NSString stringWithFormat:@"Version %2d",row+1] forMenu:result];
324        return result;
325}
326
327- (NSString *) titleForRow: (long) row
328{
329        if(row > [posters count])
330                return nil;
331
332        if (refreshInvoke != nil && row == [posters count])
333                return BRLocalizedString(@"Refresh", @"Reload images");
334
335        return [NSString stringWithFormat:@"Version %2d",row+1];
336}
337
338- (long) rowForTitle: (NSString *) title
339{
340    long result = -1;
341    long i, count = [self itemCount];
342    for ( i = 0; i < count; i++ )
343    {
344        if ( [title isEqualToString: [self titleForRow: i]] )
345       {
346            result = i;
347            break;
348       }
349    }
350    return ( result );
351}
352
353/*!
354 * @brief load poster image layers
355 *
356 * @param The index of the poster to load
357 */
358- (void) loadPoster:(int)index;
359{
360        NSString *poster = [posters objectAtIndex:index];
361        NSString *posterDest=[NSString stringWithFormat:@"%@/%@",
362                [applicationSupportDir() stringByAppendingPathComponent:@"Poster_Buffer"],
363                [poster lastPathComponent]];
364        [posterLayers replaceObjectAtIndex:index withObject:[self getPosterLayer:posterDest]];
365}
366
367- (BRBlurryImageLayer *) getPosterLayer: (NSString *) thePosterPath
368{
369        if([SapphireFrontRowCompat usingFrontRow])
370        {
371                /*The marching icons has changed, dramatically, so we do the changes here*/
372                id ret = [SapphireFrontRowCompat imageAtPath:thePosterPath];
373                if(ret != nil)
374                        return ret;
375                else
376                        return defaultImage;
377        }
378    NSURL * posterURL = [NSURL fileURLWithPath: thePosterPath];
379       
380    if (posterURL==nil)
381                return nil;
382        CGImageRef posterImage=NULL;
383        CGImageSourceRef  sourceRef;   
384    sourceRef = CGImageSourceCreateWithURL((CFURLRef)posterURL, NULL);
385    if(sourceRef) {
386        posterImage = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
387        CFRelease(sourceRef);
388    }
389    if(posterImage==nil)
390                return defaultImage;
391       
392    struct BRBitmapDataInfo info;
393    info.internalFormat = GL_RGBA;
394    info.dataFormat = GL_BGRA;
395    info.dataType = GL_UNSIGNED_INT_8_8_8_8_REV;
396    info.width = 510;
397    info.height = 755;
398       
399    BRRenderContext * context = [[self scene] resourceContext];
400               
401    NSData * data = CreateBitmapDataFromImage(posterImage,info.width,info.height );
402    BRBitmapTexture * lucid = [[BRBitmapTexture alloc] initWithBitmapData: data
403                                                                                                                           bitmapInfo: &info
404                                                                                                                                  context: context
405                                                                                                                                   mipmap: YES];
406    [data release];
407       
408    BRBitmapTexture * blur = [BRBlurryImageLayer blurredImageForImage: posterImage
409                                                            inContext: context
410                                                                 size: NSMakeSize(510.0f, 755.0f)];
411       
412    CFRelease( posterImage );
413       
414    BRBlurryImageLayer * result = [BRBlurryImageLayer layerWithScene: [self scene]];
415       
416    [result setLucidImage: lucid withReflection: nil];
417    [result setBlurryImage: blur withReflection: nil];
418       
419    [lucid release];
420       
421    return ( result );
422}
423
424- (void) hideIconMarch
425{
426        /* Might want to free memory here since posters won't be chosen again */
427    [posterMarch removeFromSuperlayer];
428}
429
430- (void) showIconMarch
431{
432        NSRect frame = [SapphireFrontRowCompat frameOfController:self];
433    frame.size.width *= 0.50f;
434        if(![SapphireFrontRowCompat usingFrontRow])
435        {
436                frame.size.height *= 1.7f;
437                frame.origin.y=-200.0f;
438        }
439        else
440                frame.size.height = ([fileInfoText frame].origin.y - frame.origin.y) * 1.2f;
441    [posterMarch setFrame: frame];
442        if(posterMarch != nil)
443                [SapphireFrontRowCompat addSublayer:posterMarch toControl:self];
444}
445
446- (void)setSelectionForPoster:(double)sel
447{
448        if(posterMarch == nil)
449                return;
450        NSMethodSignature *signature = [posterMarch methodSignatureForSelector:@selector(setSelection:)];
451        NSInvocation *selInv = [NSInvocation invocationWithMethodSignature:signature];
452        [selInv setSelector:@selector(setSelection:)];
453        if(strcmp([signature getArgumentTypeAtIndex:2], "l"))
454        {
455                double dvalue = sel;
456                [selInv setArgument:&dvalue atIndex:2];
457        }
458        else
459        {
460                long lvalue = sel;
461                [selInv setArgument:&lvalue atIndex:2];
462        }
463        [selInv invokeWithTarget:posterMarch];
464}
465
466- (void) selectionChanged: (NSNotification *) note
467{
468        /* ATV version 1.1 */
469        if([(BRListControl *)[note object] respondsToSelector:@selector(renderSelection)])
470                [self setSelectionForPoster:[(BRListControl *)[note object] renderSelection]];
471        /* ATV version 1.0 */
472        else
473                [self setSelectionForPoster:[(BRListControl *)[note object] selection]];
474}
475
476- (id<BRMediaPreviewController>) previewControlForItem: (long) row
477{
478        if(posterMarch != nil)
479                return nil;
480
481        SapphireMediaPreview *preview = [[SapphireMediaPreview alloc] initWithScene:[self scene]];
482        [preview setShowsMetadataImmediately:YES];
483       
484        if ( row < [posters count] )
485        {
486                [preview setMetaData:meta inMetaData:[meta parent]];
487               
488                SapphireMedia *asset = [[SapphireMedia alloc] initWithMediaURL:[NSURL fileURLWithPath:@"none"]];
489                id poster = [posters objectAtIndex:row];
490
491                if ( [poster isKindOfClass:[NSString class]] )
492                {
493                        NSString *posterDest = [NSString stringWithFormat:@"%@/%@",     [applicationSupportDir() stringByAppendingPathComponent:@"Poster_Buffer"],
494                                                                                                                                                [poster lastPathComponent]];
495                        [asset setImagePath: posterDest];
496                }
497                else
498                {
499                        [asset setImage: poster];
500                }
501
502                [preview setAsset:asset];
503                [asset release];
504        }
505        else if ( row == [posters count] )
506        {
507                NSMutableDictionary *refreshMeta = [[NSMutableDictionary alloc] init];
508                [refreshMeta setObject: BRLocalizedString( @"Refresh the artwork selection", @"Refresh the artwork selection" ) forKey: META_TITLE_KEY];
509                [preview setUtilityData: refreshMeta];
510        }
511
512        return [preview autorelease];
513}
514
515- (id<BRMediaPreviewController>) previewControllerForItem: (long) row
516{
517        return [self previewControlForItem:row];
518}
519
520
521@end
Note: See TracBrowser for help on using the repository browser.