source: trunk/SapphireCompatibilityClasses/SapphireFrontRowCompat.m @ 893

Revision 893, 16.4 KB checked in by gbooker, 5 years ago (diff)

Added some of the convenience functions back, under a different name to be clearer about what they do.

Line 
1/*
2 * SapphireFrontRowCompat.m
3 * Sapphire
4 *
5 * Created by Graham Booker on Oct. 29, 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 "SapphireFrontRowCompat.h"
22#import <ExceptionHandling/NSExceptionHandler.h>
23#import "SapphireButtonControl.h"
24
25/*Yes, this is the wrong class, but otherwise gcc gripes about BRImage class not existing; this removes warnings so no harm*/
26@interface SapphireFrontRowCompat (compat)
27+ (id)imageWithPath:(NSString *)path;
28- (id)downsampledImageForMaxSize:(NSSize)size;
29+ (id)imageWithCGImageRef:(CGImageRef)ref;
30- (CGImageRef)image;
31@end
32
33NSData *CreateBitmapDataFromImage(CGImageRef image, unsigned int width, unsigned int height);
34
35/*Yes, wrong class and other wrong things, just to shut up warnings*/
36@interface BRAdornedMenuItemLayer (compat)
37+ (id)folderMenuItem;
38+ (id)menuItem;
39- (void)setTitle:(NSString *)title;
40- (void)setTitle:(NSString *)title withAttributes:(NSDictionary *)attributes;
41- (void)setRightJustifiedText:(NSString *)text;
42- (void)setLeftIconInfo:(BRTexture *)icon;
43- (void)setRightIconInfo:(BRTexture *)icon;
44@end
45
46@interface BRThemeInfo (compat)
47- (id)selectedSettingImage;
48- (id)unplayedPodcastImage;
49- (id)unplayedVideoImage;
50- (id)returnToImage;
51@end
52
53@interface BRButtonControl (compat)
54- (id)initWithMasterLayerSize:(NSSize)fp8;
55@end
56
57@interface BRTextControl (compat)
58- (void)setText:(NSString *)text withAttributes:(NSDictionary *)attr;
59- (NSRect)controllerFrame;  /*technically wrong; it is really a CGRect*/
60- (NSSize)renderedSizeWithMaxSize:(NSSize)maxSize; /*technically wrong; it is really a CGSize*/
61@end
62
63@interface NSException (compat)
64- (NSArray *)callStackReturnAddresses;
65@end
66
67@interface BRAlertController (compat)
68+ (BRAlertController *)alertOfType:(int)type titled:(NSString *)title primaryText:(NSString *)primaryText secondaryText:(NSString *)secondaryText;
69@end
70
71@interface BROptionDialog (compat)
72- (void)setPrimaryInfoText:(NSString *)text withAttributes:(NSDictionary *)attributes;
73@end
74
75@interface BRTextWithSpinnerController (compat)
76- (BRTextWithSpinnerController *)initWithTitle:(NSString *)title text:(NSString *)text isNetworkDependent:(BOOL)networkDependent;
77@end
78
79@interface BRControl (compat)
80- (void)insertControl:(id)control atIndex:(long)index;
81@end
82
83@interface BRWaitSpinnerControl (compat)
84- (void)setSpins:(BOOL)spin;
85@end
86
87@interface BRTextEntryControl (compat)
88- (id)initWithTextEntryStyle:(int)style;
89@end
90
91
92@implementation SapphireFrontRowCompat
93
94static SapphireFrontRowCompatATVVersion atvVersion = SapphireFrontRowCompatATVVersionUnknown;
95static BOOL usingLeopard = NO;
96static BOOL usingATypeOfTakeTwo = NO;
97static BOOL usingLeopardOrATypeOfTakeTwo = NO;
98
99+ (void)initialize
100{
101        if(NSClassFromString(@"BRAdornedMenuItemLayer") == nil)
102        {
103                atvVersion = SapphireFrontRowCompatATVVersionLeopardFrontrow;
104                usingLeopard = YES;
105                usingLeopardOrATypeOfTakeTwo = YES;
106        }
107       
108        if(NSClassFromString(@"BRBaseAppliance") != nil)
109        {
110                atvVersion = SapphireFrontRowCompatATVVersion2;
111                usingLeopard = NO;
112                usingATypeOfTakeTwo = YES;
113        }
114       
115        if(NSClassFromString(@"BRVideoPlayerController") == nil)
116                atvVersion = SapphireFrontRowCompatATVVersion2Dot2;
117       
118        if([(Class)NSClassFromString(@"BRController") instancesRespondToSelector:@selector(wasExhumed)])
119                atvVersion = SapphireFrontRowCompatATVVersion2Dot3;
120       
121        if(NSClassFromString(@"BRPhotoImageProxy") != nil)
122                atvVersion = SapphireFrontRowCompatATVVersion2Dot4;
123}
124
125+ (SapphireFrontRowCompatATVVersion)atvVersion
126{
127        return atvVersion;
128}
129
130+ (BOOL)usingLeopard
131{
132        return usingLeopard;
133}
134
135+ (BOOL)usingATypeOfTakeTwo
136{
137        return usingATypeOfTakeTwo;
138}
139
140+ (BOOL)usingLeopardOrATypeOfTakeTwo
141{
142        return usingLeopardOrATypeOfTakeTwo;
143}
144
145+ (BOOL)usingFrontRow
146{
147        return atvVersion >= SapphireFrontRowCompatATVVersionLeopardFrontrow;
148}
149
150+ (BOOL)usingTakeTwo
151{
152        return atvVersion >= SapphireFrontRowCompatATVVersion2;
153}
154
155+ (BOOL)usingTakeTwoDotTwo
156{
157        return atvVersion >= SapphireFrontRowCompatATVVersion2Dot2;
158}
159
160+ (BOOL)usingTakeTwoDotThree
161{
162        return atvVersion >= SapphireFrontRowCompatATVVersion2Dot3;
163}
164
165+ (BOOL)usingTakeTwoDotFour
166{
167        return atvVersion >= SapphireFrontRowCompatATVVersion2Dot4;
168}
169
170+ (id)imageAtPath:(NSString *)path
171{
172        if(usingLeopardOrATypeOfTakeTwo) {
173                Class cls = NSClassFromString(@"BRImage");
174                return [cls imageWithPath:path];
175        } else {
176                // this returns a CGImageRef
177                NSURL             *url      = [NSURL fileURLWithPath:path];
178                CGImageRef        imageRef  = NULL;
179                CGImageSourceRef  sourceRef;
180               
181                sourceRef = CGImageSourceCreateWithURL((CFURLRef)url, NULL);
182                if(sourceRef) {
183                        imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL);
184                        CFRelease(sourceRef);
185                }
186               
187                return [(id)imageRef autorelease];
188        }
189}
190
191+ (id)imageAtPath:(NSString *)path scene:(BRRenderScene *)scene
192{
193        if(usingLeopardOrATypeOfTakeTwo) {
194                return [self imageAtPath:path];
195        } else {
196                CGImageRef imageRef  = (CGImageRef)[self imageAtPath:path];
197                BRTexture  *ret      = nil;
198               
199                if(imageRef != NULL) {
200                        /*Create a texture*/
201                        ret = [BRBitmapTexture textureWithImage:imageRef context:[scene resourceContext] mipmap:YES];
202                }
203               
204                return ret;
205        }
206}
207
208+ (id)coverartAsImage: (CGImageRef)imageRef
209{
210        // Non-FR - return CGImageRef
211        if (!usingLeopardOrATypeOfTakeTwo)
212                return (id)imageRef;
213       
214        // FR - return BRImage
215        Class cls = NSClassFromString(@"BRImage");
216        return (id)[cls imageWithCGImageRef:imageRef];
217}
218
219+ (BRAdornedMenuItemLayer *)textMenuItemForScene:(BRRenderScene *)scene folder:(BOOL)folder
220{
221        if(usingLeopardOrATypeOfTakeTwo)
222        {
223                if(folder)
224                        return [NSClassFromString(@"BRTextMenuItemLayer") folderMenuItem];
225                else
226                        return [NSClassFromString(@"BRTextMenuItemLayer") menuItem];           
227        }
228        else
229        {
230                if(folder)
231                        return [NSClassFromString(@"BRAdornedMenuItemLayer") adornedFolderMenuItemWithScene:scene];
232                else
233                        return [NSClassFromString(@"BRAdornedMenuItemLayer") adornedMenuItemWithScene:scene];           
234        }
235}
236
237+ (void)setTitle:(NSString *)title forMenu:(BRAdornedMenuItemLayer *)menu
238{
239        if(usingLeopardOrATypeOfTakeTwo)
240                [menu setTitle:title];
241        else
242                [[menu textItem] setTitle:title];
243}
244
245+ (void)setTitle:(NSString *)title withAttributes:(NSDictionary *)attributes forMenu:(BRAdornedMenuItemLayer *)menu
246{
247        if(usingLeopardOrATypeOfTakeTwo)
248                [menu setTitle:title withAttributes:attributes];
249        else
250                [[menu textItem] setTitle:title withAttributes:attributes];
251}
252
253+ (NSString *)titleForMenu:(BRAdornedMenuItemLayer *)menu {
254        if(usingLeopardOrATypeOfTakeTwo)
255                return [menu title];
256        else
257                return [[menu textItem] title];
258}
259+ (void)setRightJustifiedText:(NSString *)text forMenu:(BRAdornedMenuItemLayer *)menu
260{
261        if(usingLeopardOrATypeOfTakeTwo)
262                [menu setRightJustifiedText:text];
263        else
264                [[menu textItem] setRightJustifiedText:text];
265}
266
267+ (void)setLeftIcon:(BRTexture *)icon forMenu:(BRAdornedMenuItemLayer *)menu
268{
269        if(usingLeopardOrATypeOfTakeTwo)
270                [menu setLeftIconInfo:[NSDictionary dictionaryWithObjectsAndKeys:
271                                                           icon, @"BRMenuIconImageKey",
272                                                           nil]];
273        else
274                [menu setLeftIcon:icon];
275}
276
277+ (void)setRightIcon:(BRTexture *)icon forMenu:(BRAdornedMenuItemLayer *)menu
278{
279        if(usingLeopardOrATypeOfTakeTwo)
280                [menu setRightIconInfo:[NSDictionary dictionaryWithObjectsAndKeys:
281                                                                icon, @"BRMenuIconImageKey",
282                                                                nil]];
283        else
284                [menu setRightIcon:icon];
285}
286
287+ (id)selectedSettingImageForScene:(BRRenderScene *)scene
288{
289        if(usingLeopardOrATypeOfTakeTwo)
290                return [[BRThemeInfo sharedTheme] selectedSettingImage];
291        else
292                return [[BRThemeInfo sharedTheme] selectedSettingImageForScene:scene];
293}
294
295+ (id)unplayedPodcastImageForScene:(BRRenderScene *)scene
296{
297        if(atvVersion >= SapphireFrontRowCompatATVVersion2Dot4)
298                return [[BRThemeInfo sharedTheme] unplayedVideoImage];
299        else if(usingLeopardOrATypeOfTakeTwo)
300                return [[BRThemeInfo sharedTheme] unplayedPodcastImage];
301        else
302                return [[BRThemeInfo sharedTheme] unplayedPodcastImageForScene:scene];
303}
304
305+ (id)returnToImageForScene:(BRRenderScene *)scene {
306        if(usingLeopardOrATypeOfTakeTwo)
307                return [[BRThemeInfo sharedTheme] returnToImage];
308        else
309                return [[BRThemeInfo sharedTheme] returnToImageForScene:scene];
310}
311
312+ (NSRect)frameOfController:(id)controller
313{
314        if(usingATypeOfTakeTwo)
315                // ATV2
316                return [controller frame];
317        else if(usingLeopard)
318                // 10.5
319                return [controller controllerFrame];
320        else
321                return [[controller masterLayer] frame];
322}
323
324+ (void)setText:(NSString *)text withAtrributes:(NSDictionary *)attributes forControl:(BRTextControl *)control
325{
326        if(usingLeopardOrATypeOfTakeTwo)
327                [control setText:text withAttributes:attributes];
328        else
329        {
330                if(attributes != nil)
331                        [control setTextAttributes:attributes];
332                [control setText:text];
333        }
334}
335
336+ (NSSize)textControl:(BRTextControl *)text renderedSizeWithMaxSize:(NSSize)maxSize
337{
338        if(usingATypeOfTakeTwo)
339                return [text renderedSizeWithMaxSize:maxSize];
340       
341        [text setMaximumSize:maxSize];
342        return [text renderedSize];
343}
344
345+ (void)addDividerAtIndex:(int)index toList:(BRListControl *)list
346{
347        if(usingLeopardOrATypeOfTakeTwo)
348                [list addDividerAtIndex:index withLabel:@""];
349        else
350                [list addDividerAtIndex:index];
351}
352
353+ (void)addSublayer:(id)sub toControl:(id)controller
354{
355        if(usingLeopardOrATypeOfTakeTwo) {
356                // ATV2
357                if(NSClassFromString(@"BRPanel") == nil)
358                        [controller addControl:sub];
359                // 10.5
360                else
361                        [[controller layer] addSublayer:sub];
362        }
363        else
364                [[controller masterLayer] addSublayer:sub];
365}
366
367+ (void)insertSublayer:(id)sub toControl:(id)controller atIndex:(long)index {
368        if(usingLeopardOrATypeOfTakeTwo) {
369                // ATV2
370                if(NSClassFromString(@"BRPanel") == nil)
371                        [controller insertControl:sub atIndex:index];
372                // 10.5
373                else
374                        [[controller layer] insertSublayer:sub atIndex:index];
375        } else
376                [[controller masterLayer] insertSublayer:sub atIndex:index];
377}
378
379+ (BRHeaderControl *)newHeaderControlWithScene:(BRRenderScene *)scene
380{
381        if(usingLeopardOrATypeOfTakeTwo)
382                return [[BRHeaderControl alloc] init];
383        else
384                return [[BRHeaderControl alloc] initWithScene:scene];
385}
386
387+ (BRButtonControl *)newButtonControlWithScene:(BRRenderScene *)scene  masterLayerSize:(NSSize)size;
388{
389        if(usingLeopardOrATypeOfTakeTwo)
390                return [[SapphireButtonControl alloc] initWithMasterLayerSize:size];
391        else
392                return [[BRButtonControl alloc] initWithScene:scene masterLayerSize:size];
393}
394
395+ (BRTextControl *)newTextControlWithScene:(BRRenderScene *)scene
396{
397        if(usingLeopardOrATypeOfTakeTwo)
398                return [[BRTextControl alloc] init];
399        else
400                return [[BRTextControl alloc] initWithScene:scene];
401}
402
403+ (BRTextEntryControl *)newTextEntryControlWithScene:(BRRenderScene *)scene
404{
405        if(usingLeopardOrATypeOfTakeTwo)
406        {
407                if(atvVersion >= SapphireFrontRowCompatATVVersion2Dot2)
408                        return [[BRTextEntryControl alloc] initWithTextEntryStyle:1];
409                return [[BRTextEntryControl alloc] initWithTextEntryStyle:0];
410        }
411        else
412                return [[BRTextEntryControl alloc] initWithScene:scene];
413}
414
415+ (BRProgressBarWidget *)newProgressBarWidgetWithScene:(BRRenderScene *)scene
416{
417        if(usingLeopardOrATypeOfTakeTwo)
418                return [[BRProgressBarWidget alloc] init];
419        else
420                return [[BRProgressBarWidget alloc] initWithScene:scene];
421}
422
423+ (BRMarchingIconLayer *)newMarchingIconLayerWithScene:(BRRenderScene *)scene
424{
425        if(usingATypeOfTakeTwo)
426                return nil;
427        if(usingLeopardOrATypeOfTakeTwo)
428                return [[BRMarchingIconLayer alloc] init];
429        else
430                return [[BRMarchingIconLayer alloc] initWithScene:scene];
431}
432
433+ (BRImageLayer *)newImageLayerWithScene:(BRRenderScene *)scene {
434        // 10.5
435        if(usingLeopardOrATypeOfTakeTwo && NSClassFromString(@"BRImageLayer") != nil)
436                return [[BRImageLayer alloc] init];
437        // ATV2
438        else if(usingLeopardOrATypeOfTakeTwo)
439                return [[NSClassFromString(@"BRImageControl") alloc] init];
440        else
441                return [[BRImageLayer layerWithScene:scene] retain];
442}
443
444+ (void)setImage:(id)image forLayer:(BRImageLayer *)layer {
445        if(usingLeopardOrATypeOfTakeTwo)
446                // this cast is not proper, it just makes a warning disappear.
447                [layer setImage:(CGImageRef)image];
448        else
449                [layer setTexture:image];
450}
451
452+ (BRImageLayer *)newImageLayerWithImage:(id)image scene:(BRRenderScene *)scene {
453        BRImageLayer *result = [self newImageLayerWithScene:scene];
454        [self setImage:image forLayer:result];
455        return result;
456}
457
458+ (void)renderScene:(BRRenderScene *)scene
459{
460        if(!usingLeopardOrATypeOfTakeTwo)
461                [scene renderScene];
462}
463
464+ (BRAlertController *)alertOfType:(int)type titled:(NSString *)title primaryText:(NSString *)primaryText secondaryText:(NSString *)secondaryText withScene:(BRRenderScene *)scene {
465        if(usingLeopardOrATypeOfTakeTwo)
466                return [BRAlertController alertOfType:type
467                                                                           titled:title
468                                                                  primaryText:primaryText
469                                                                secondaryText:secondaryText];
470        else
471                return [BRAlertController alertOfType:type
472                                                                           titled:title
473                                                                  primaryText:primaryText
474                                                                secondaryText:secondaryText
475                                    withScene:scene];
476}
477
478+ (BROptionDialog *)newOptionDialogWithScene:(BRRenderScene *)scene {
479        if(usingLeopardOrATypeOfTakeTwo)
480                return [[BROptionDialog alloc] init];
481        else
482                return [[BROptionDialog alloc] initWithScene:scene];
483}
484
485+ (void)setOptionDialogPrimaryInfoText:(NSString *)primaryInfoText withAttributes:(NSDictionary *)attributes optionDialog:(BROptionDialog *)dialog {
486        if(usingLeopardOrATypeOfTakeTwo) {
487                [dialog setPrimaryInfoText:primaryInfoText withAttributes:attributes];
488        } else {
489                [dialog setPrimaryInfoText:primaryInfoText];
490                [dialog setPrimaryInfoTextAttributes:attributes];
491        }
492}
493
494+ (BRTextWithSpinnerController *)newTextWithSpinnerControllerTitled:(NSString *)title text:(NSString *)text isNetworkDependent:(BOOL)networkDependent scene:(BRRenderScene *)scene {
495        if(usingLeopardOrATypeOfTakeTwo)
496                return [[BRTextWithSpinnerController alloc] initWithTitle:title text:text isNetworkDependent:networkDependent];
497        else
498                return [[BRTextWithSpinnerController alloc] initWithScene:scene title:title text:text showBack:NO isNetworkDependent:NO];
499}
500
501+ (void)setSpinner:(BRWaitSpinnerControl *)spinner toSpin:(BOOL)spin
502{
503        if([spinner respondsToSelector:@selector(setSpins:)])
504                [spinner setSpins:spin];
505        else if([spinner respondsToSelector:@selector(startSpinning)])
506        {
507                if(spin)
508                        [spinner startSpinning];
509                else
510                        [spinner stopSpinning];
511        }
512}
513
514+ (BREventRemoteAction)remoteActionForEvent:(BREvent *)event
515{
516        if(atvVersion >= SapphireFrontRowCompatATVVersion2Dot4)
517                return [event remoteAction];
518       
519        BREventPageUsageHash hashVal = (uint32_t)([event page] << 16 | [event usage]);
520        switch (hashVal) {
521                case kBREventTapMenu:
522                        return kBREventRemoteActionMenu;
523                case kBREventTapPlayPause:
524                        return kBREventRemoteActionPlay;
525                case kBREventTapRight:
526                        return kBREventRemoteActionRight;
527                case kBREventTapLeft:
528                        return kBREventRemoteActionLeft;
529                case kBREventTapUp:
530                case kBREventHoldUp:
531                        return kBREventRemoteActionUp;
532                case kBREventTapDown:
533                case kBREventHoldDown:
534                        return kBREventRemoteActionDown;
535                case kBREventHoldMenu:
536                        return kBREventRemoteActionMenuHold;
537                case kBREventHoldPlayPause:
538                        return kBREventRemoteActionPlayHold;
539                       
540                        //Unknowns:
541                case kBREventTapExit:
542                case kBREventHoldLeft:
543                case kBREventHoldRight:
544                case kBREventPlay:
545                case kBREventPause:
546                case kBREventFastForward:
547                case kBREventRewind:
548                case kBREventNextTrack:
549                case kBREventPreviousTrack:
550                case kBREventStop:
551                case kBREventEject:
552                case kBREventRandomPlay:
553                case kBREventVolumeUp:
554                case kBREventVolumeDown:
555                case kBREventPairRemote:
556                case kBREventUnpairRemote:
557                case kBREventLowBattery:
558                case kBREventSleepNow:
559                case kBREventSystemReset:
560                case kBREventBlackScreenRecovery:
561                default:
562                        return 0;
563        }
564}
565
566+ (NSArray *)callStackReturnAddressesForException:(NSException *)exception
567{
568        if([exception respondsToSelector:@selector(callStackReturnAddresses)])
569        {
570                NSArray *ret = [exception callStackReturnAddresses];
571                if([ret count])
572                        return ret;
573        }
574        return [[exception userInfo] objectForKey:NSStackTraceKey];
575}
576
577+ (RUIPreferences *)sharedFrontRowPreferences {
578        Class preferencesClass = NSClassFromString(@"RUIPreferences");
579        if(!preferencesClass) preferencesClass = NSClassFromString(@"BRPreferences");
580       
581        if(preferencesClass)
582                return [preferencesClass sharedFrontRowPreferences];
583        else
584                return nil;
585}
586
587@end
Note: See TracBrowser for help on using the repository browser.