source: trunk/SapphireCompatibilityClasses/SapphireFrontRowCompat.h @ 895

Revision 895, 17.1 KB checked in by gbooker, 5 years ago (diff)

Expanded the remote actions compatibility so that it handles the old remote actions for holding left and right which are gone as of 2.2

Line 
1/*
2 * SapphireFrontRowCompat.h
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// Gesture events have a dictionary defining the touch points and other info.
22typedef enum {
23        kBREventOriginatorRemote = 1,
24        kBREventOriginatorGesture = 3
25} BREventOriginator;
26
27typedef enum {
28        // for originator kBREventOriginatorRemote
29        kBREventRemoteActionMenu = 1,
30        kBREventRemoteActionMenuHold,
31        kBREventRemoteActionUp,
32        kBREventRemoteActionDown,
33        kBREventRemoteActionPlay,
34        kBREventRemoteActionLeft,
35        kBREventRemoteActionRight,
36
37        kBREventRemoteActionPlayHold = 20,
38
39        // Gestures, for originator kBREventOriginatorGesture
40        kBREventRemoteActionTap = 30,
41        kBREventRemoteActionSwipeLeft,
42        kBREventRemoteActionSwipeRight,
43        kBREventRemoteActionSwipeUp,
44        kBREventRemoteActionSwipeDown,
45       
46        // Custom remote actions for old remote actions
47        kBREventRemoteActionHoldLeft = 0xfeed0001,
48        kBREventRemoteActionHoldRight,
49        kBREventRemoteActionHoldUp,
50        kBREventRemoteActionHoldDown,
51} BREventRemoteAction;
52
53/*!
54 * @brief A compatibility category for frontrow
55 *
56 * This is just here to make the compiler shut up.  The sharedInstance does not exist on the ATV, but it does on frontrow.  It is only called on frontrow.
57 */
58@interface BRRenderScene (compat)
59/*!
60 * @brief Get the shared insntance
61 *
62 * @return The shared instance
63 */
64+ (BRRenderScene *)sharedInstance;
65@end
66
67typedef enum {
68        SapphireFrontRowCompatATVVersionUnknown = 0,
69        SapphireFrontRowCompatATVVersion1 = 1,
70        SapphireFrontRowCompatATVVersionLeopardFrontrow,
71        SapphireFrontRowCompatATVVersion2,
72        SapphireFrontRowCompatATVVersion2Dot2,
73        SapphireFrontRowCompatATVVersion2Dot3,
74        SapphireFrontRowCompatATVVersion2Dot4,
75} SapphireFrontRowCompatATVVersion;
76
77/*!
78 * @brief A compatibility class for frontrow
79 *
80 * This class provides many compatibility functions for frontrow.  This class is never instanciated since it contains no data.  All of these functions could be implemented with C functions, but that looses the clarity of the exact meaning of parameters in Obj-C calls.
81 */
82@interface SapphireFrontRowCompat : NSObject {
83}
84
85/*!
86 * @brief Determine the ATV version
87 *
88 * @return The ATV Version
89 */
90+ (SapphireFrontRowCompatATVVersion)atvVersion;
91
92/*!
93 * @brief Are we on a leopard machine?
94 *
95 * @return YES if on leopard, NO otherwise
96 */
97+ (BOOL)usingLeopard;
98
99/*!
100 * @brief Are we on a type of ATV Take Two?
101 *
102 * @return YES if on take two, NO otherwise
103 */
104+ (BOOL)usingATypeOfTakeTwo;
105
106/*!
107 * @brief Are we on leopard or a type of ATV Take Two?
108 *
109 * @return YES if on leopard or take 2, NO otherwise
110 */
111+ (BOOL)usingLeopardOrATypeOfTakeTwo;
112
113/*!
114 * @brief Load an image at a path
115 *
116 * This returns a CGImageRef or a BRImage, depending on platform.
117 *
118 * @return The BRImage on Front Row or CGImageRef on ATV at a path
119 */
120+ (id)imageAtPath:(NSString *)path;
121
122/*!
123 * @brief Load an image texture at a path
124 *
125 * This is like imageAtPath:, only it will return a BRBitmapTexture
126 * on the ATV for setting as a menu item icon.
127 *
128 * @return BRImage or BRBitmapTexture at a path
129 */
130+ (id)imageAtPath:(NSString *)path scene:(BRRenderScene *)scene;
131
132/*!
133 * @brief Load an image from an Image Ref
134 *
135 * This returns a CGImageRef or a BRImage, depending on platform.
136 *
137 * @param[in]   imageRef  CGImageRef
138 * @return  BRImage on FrontRow of CGImageRef on ATV
139 */
140+ (id)coverartAsImage: (CGImageRef)imageRef;
141
142/*!
143 * @brief Get a menu text menu item
144 *
145 * Menu items are of different classes on the ATV and in frontrow.
146 *
147 * @param scene The scene, if exists
148 * @param folder YES if this is a folder, NO otherwise
149 * @return The new menu item
150 */
151+ (BRAdornedMenuItemLayer *)textMenuItemForScene:(BRRenderScene *)scene folder:(BOOL)folder;
152
153/*!
154 * @brief Set a menu item's title
155 *
156 * Menu items work differently in fronrow
157 *
158 * @param title The new title
159 * @param menu The menu item to set
160 */
161+ (void)setTitle:(NSString *)title forMenu:(BRAdornedMenuItemLayer *)menu;
162
163/*!
164 * @brief Set a menu item's title with attributes
165 *
166 * Menu items work differently in fronrow
167 *
168 * @param title The new title
169 * @param attributes The new attributes
170 * @param menu The menu item to set
171 */
172+ (void)setTitle:(NSString *)title withAttributes:(NSDictionary *)attributes forMenu:(BRAdornedMenuItemLayer *)menu;
173
174/*!
175 * @brief Get a menu item's title
176 *
177 * Menu items work differently in frontrow
178 *
179 * @param menu The menu item
180 */
181+ (NSString *)titleForMenu:(BRAdornedMenuItemLayer *)menu;
182
183/*!
184 * @brief Set a menu item's right justified text
185 *
186 * Menu items work differently in fronrow
187 *
188 * @param text The new text
189 * @param menu The menu item to set
190 */
191+ (void)setRightJustifiedText:(NSString *)text forMenu:(BRAdornedMenuItemLayer *)menu;
192
193/*!
194 * @brief Set a menu item's left icon
195 *
196 * Menu items work differently in fronrow
197 *
198 * @param icon The new icon
199 * @param menu The menu item to set
200 */
201+ (void)setLeftIcon:(BRTexture *)icon forMenu:(BRAdornedMenuItemLayer *)menu;
202
203/*!
204 * @brief Set a menu item's right icon
205 *
206 * Menu items work differently in fronrow
207 *
208 * @param icon The new icon
209 * @param menu The menu item to set
210 */
211+ (void)setRightIcon:(BRTexture *)icon forMenu:(BRAdornedMenuItemLayer *)menu;
212
213/*!
214 * @brief Get the checkmark image
215 *
216 * @param scene The secen, if exists
217 * @return The checkmark image
218 */
219+ (id)selectedSettingImageForScene:(BRRenderScene *)scene;
220
221/*!
222 * @brief Get the blue unplayed dot image
223 *
224 * @param scene The scene, if it exists
225 * @return The blue unplayed dot image
226 */
227+ (id)unplayedPodcastImageForScene:(BRRenderScene *)scene;
228
229/*!
230 * @brief Get the return to arrow image
231 *
232 * @param scene The scene, if it exists
233 * @return The return to arrow image
234 */ 
235+ (id)returnToImageForScene:(BRRenderScene *)scene;
236
237/*!
238 * @brief Get a controller's frame
239 *
240 * Controllers work differently in fronrow
241 *
242 * @param controller The controller
243 * @return The frame of the controller
244 */
245+ (NSRect)frameOfController:(id)controller;
246
247/*!
248 * @brief Set a controller's text
249 *
250 * Controllers work differently in fronrow
251 *
252 * @param text The new text
253 * @param attributes The new text's attributes
254 * @param control The control to set
255 */
256+ (void)setText:(NSString *)text withAtrributes:(NSDictionary *)attributes forControl:(BRTextControl *)control;
257
258/*!
259 * @brief Add a divider to a menu
260 *
261 * Lists work differently in fronrow
262 *
263 * @param index The index to add the divider
264 * @param list The list to add to
265 */
266+ (void)addDividerAtIndex:(int)index toList:(BRListControl *)list;
267
268/*!
269 * @brief Add a sublayer to a control
270 *
271 * Controllers work differently in fronrow
272 *
273 * @param sub The sublayer toadd
274 * @param controller The controller to add to
275 */
276+ (void)addSublayer:(id)sub toControl:(id)controller;
277
278/*!
279 * @brief Insert a sublayer at a position in a control
280 *
281 * Controllers and layers are different in frontrow
282 *
283 * @param sub The sublayer to add
284 * @param controller The controller to add to
285 * @param index The index to add the sublayer at
286 */
287+ (void)insertSublayer:(id)sub toControl:(id)controller atIndex:(long)index;
288
289/*!
290 * @brief Create a new header control
291 *
292 * Controllers are alloced differently in frontrow
293 *
294 * @param scene The scene, if exists.
295 */
296+ (BRHeaderControl *)newHeaderControlWithScene:(BRRenderScene *)scene;
297
298/*!
299 * @brief Create a new button control
300 *
301 * Controllers are alloced differently in frontrow
302 *
303 * @param scene The scene, if exists.
304 * @param size The size of the button
305 */
306+ (BRButtonControl *)newButtonControlWithScene:(BRRenderScene *)scene masterLayerSize:(NSSize)size;
307
308/*!
309 * @brief Create a new text control
310 *
311 * Controllers are alloced differently in frontrow
312 *
313 * @param scene The scene, if exists.
314 */
315+ (BRTextControl *)newTextControlWithScene:(BRRenderScene *)scene;
316
317/*!
318 * @brief Get the text control's rendered size within constraints
319 *
320 * @param text The text control
321 * @param maxSize The contrained maximum size
322 * @return The rendered size
323 */
324+ (NSSize)textControl:(BRTextControl *)text renderedSizeWithMaxSize:(NSSize)maxSize;
325
326/*!
327 * @brief Create a new text entry control
328 *
329 * Controllers are alloced differently in frontrow
330 *
331 * @param scene The scene, if exists.
332 */
333+ (BRTextEntryControl *)newTextEntryControlWithScene:(BRRenderScene *)scene;
334
335/*!
336 * @brief Create a new progress bar widget
337 *
338 * Widgets are alloced differently in frontrow
339 *
340 * @param scene The scene, if exists.
341 */
342+ (BRProgressBarWidget *)newProgressBarWidgetWithScene:(BRRenderScene *)scene;
343
344/*!
345 * @brief Create a new marching icon layer
346 *
347 * Layers are alloced differently in frontrow
348 *
349 * @param scene The scene, if exists.
350 */
351+ (BRMarchingIconLayer *)newMarchingIconLayerWithScene:(BRRenderScene *)scene;
352
353/*!
354 * @brief Create a new image layer
355 *
356 * Layers are different in frontrow
357 *
358 * @param scene The scene, if it exists.
359 */
360+ (BRImageLayer *)newImageLayerWithScene:(BRRenderScene *)scene;
361
362/*!
363 * @brief Set the image on a BRImageLayer
364 *
365 * FR uses BRImage instead of BRTexture
366 *
367 * @param image The image (BRImage on FR/BRTexture on ATV)
368 */
369+ (void)setImage:(id)image forLayer:(BRImageLayer *)layer;
370
371/*!
372 * @brief Create a new image layer with an image
373 *
374 * Just a shortcut around the previous two
375 *
376 * @param image The image (BRImage on FR/BRTexture on ATV)
377 * @param scene The scene, if it exists.
378 */
379+ (BRImageLayer *)newImageLayerWithImage:(id)image scene:(BRRenderScene *)scene;
380
381/*!
382 * @brief Render scene on the ATV
383 *
384 * Only does something on the ATV; frontrow has no need for this
385 *
386 * @param scene The scene to render, if exists.
387 */
388+ (void)renderScene:(BRRenderScene *)scene;
389
390/*!
391 * @brief Create a new BRAlertController
392 *
393 * Scene doesn't exist on frontrow
394 *
395 * @param type The type of the alert
396 * @param titled The title of the alert
397 * @param primaryText the primary text of the alert
398 * @param secondaryText the secondary text of the alert
399 * @param scene the scene
400 */
401+ (BRAlertController *)alertOfType:(int)type titled:(NSString *)title primaryText:(NSString *)primaryText secondaryText:(NSString *)secondaryText withScene:(BRRenderScene *)scene;
402
403/*!
404 * @brief Create a new BROptionDialog
405 *
406 * Scene doesn't exist in frontrow
407 *
408 * @param scene the scene
409 */
410+ (BROptionDialog *)newOptionDialogWithScene:(BRRenderScene *)scene;
411
412/*!
413 * @brief Set the primary info text on a BROptionDialog
414 *
415 * Text/attributes are different on frontrow
416 *
417 * @param primaryInfoText the primary info text
418 * @param attributes the attributes
419 * @param dialog the BROptionDialog
420 */
421+ (void)setOptionDialogPrimaryInfoText:(NSString *)primaryInfoText withAttributes:(NSDictionary *)attributes optionDialog:(BROptionDialog *)dialog;
422
423/*!
424 * @brief Create a new BRTextWithSpinnerController
425 *
426 * Method is different on frontrow
427 *
428 * @param title the title
429 * @param text the text
430 * @param networkDependent unknown
431 * @param scene the scene
432 */
433+ (BRTextWithSpinnerController *)newTextWithSpinnerControllerTitled:(NSString *)title text:(NSString *)text isNetworkDependent:(BOOL)networkDependent scene:(BRRenderScene *)scene;
434
435/*!
436 * @brief Sets whether a BRWaitSpinnerControl should spin or not
437 *
438 * @param spinner The spinner
439 * @param spin YES if the spinner should spin, NO otherwise
440 */
441+ (void)setSpinner:(BRWaitSpinnerControl *)spinner toSpin:(BOOL)spin;
442
443/*!
444 * @brief Get the remoteAction in a compatable way
445 *
446 * @param event The event for which to fetch the remote action
447 * @return The remote action for the event
448 */
449+ (BREventRemoteAction)remoteActionForEvent:(BREvent *)event;
450
451/*!
452 * @brief Get the call stack addresses for an exception
453 *
454 * This function exists mostly because this method is different on Tiger and Leopard.  This is not a significant differece between the ATV and Frontrow
455 *
456 * @param exception The exception to examine
457 * @return An array of call addresses if successful, nil otherwise
458 */
459+ (NSArray *)callStackReturnAddressesForException:(NSException *)exception;
460
461/*!
462 * @brief Get the sharedFrontRowPreferences object.
463 *
464 * On Apple TV < 2.1, the RUIPreferences class is used for this.  On 2.1, the class is renamed to BRPreferences.
465 *
466 * @return the preferences object
467 */
468+ (RUIPreferences *)sharedFrontRowPreferences;
469@end
470
471@interface SapphireFrontRowCompat (SapphireFrontRowCompatDeprecated)
472/*!
473 * @brief Are we on frontrow?
474 *
475 * @return YES if on frontrow, NO otherwise
476 */
477+ (BOOL)usingFrontRow DEPRECATED_ATTRIBUTE;
478
479/*!
480 * @brief Are we on ATV Take Two?
481 *
482 * @return YES if on take two, NO otherwise
483 */
484+ (BOOL)usingTakeTwo DEPRECATED_ATTRIBUTE;
485
486/*!
487 * @brief Are we on ATV 2.2?
488 *
489 * @return YES if on 2.2, NO otherwise
490 */
491+ (BOOL)usingTakeTwoDotTwo DEPRECATED_ATTRIBUTE;
492
493/*!
494 * @brief Are we on ATV 2.3?
495 *
496 * @return YES if on 2.3, NO otherwise
497 */
498+ (BOOL)usingTakeTwoDotThree DEPRECATED_ATTRIBUTE;
499
500/*!
501 * @brief Are we on ATV 2.4?
502 *
503 * @return YES if on 2.4, NO otherwise
504 */
505+ (BOOL)usingTakeTwoDotFour DEPRECATED_ATTRIBUTE;
506@end
507
508
509static inline void SapphireLoadFramework(NSString *frameworkPath)
510{
511        CFStringRef preferencesDomain = CFSTR("com.apple.frontrow.appliance.Sapphire.CompatClasses");
512        CFStringRef loadPathKey = CFSTR("loadPath");
513        CFPreferencesAppSynchronize(preferencesDomain);
514        CFPropertyListRef loadPathProperty = CFPreferencesCopyAppValue(loadPathKey, preferencesDomain);
515        CFStringRef loadPath = nil;
516        if(loadPathProperty != nil && CFGetTypeID(loadPathProperty) == CFStringGetTypeID())
517                loadPath = (CFStringRef)loadPathProperty;
518       
519        NSString *compatPath = [frameworkPath stringByAppendingPathComponent:@"SapphireCompatClasses.framework"];
520        NSBundle *compat = [NSBundle bundleWithPath:compatPath];
521       
522        if(NSClassFromString(@"SapphireFrontRowCompat") == nil)
523        {
524                if(loadPath != nil)
525                {
526                        NSBundle *otherBundle = [NSBundle bundleWithPath:(NSString *)loadPath];
527                        NSString *myVersion = [compat objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
528                        NSString *otherVersion = [otherBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
529                       
530                        if(otherVersion != nil && [myVersion compare:otherVersion] == NSOrderedAscending)
531                                compat = otherBundle;
532                }
533               
534                if( ![compat load]){ 
535                        @throw [NSException exceptionWithName:@"FileNotFoundException" reason:[NSString stringWithFormat:@"SapphireCompatClasses could not be loaded from path %@", compatPath] userInfo:nil];
536                }
537                if([SapphireFrontRowCompat usingLeopardOrATypeOfTakeTwo])
538                {
539                        compatPath = [frameworkPath stringByAppendingPathComponent:@"SapphireLeopardCompatClasses.framework"];
540                        compat = [NSBundle bundleWithPath:compatPath];
541                        if( ![compat load]){ 
542                                @throw [NSException exceptionWithName:@"FileNotFoundException" reason:[NSString stringWithFormat:@"SapphireLeopardCompatClasses could not be loaded from path %@", compatPath] userInfo:nil];
543                        }
544                }
545                // ATV2
546                if([SapphireFrontRowCompat usingATypeOfTakeTwo])
547                {
548                        compatPath = [frameworkPath stringByAppendingPathComponent:@"SapphireTakeTwoCompatClasses.framework"];
549                        compat = [NSBundle bundleWithPath:compatPath];
550                        if( ![compat load]){ 
551                                @throw [NSException exceptionWithName:@"FileNotFoundException" reason:[NSString stringWithFormat:@"SapphireTakeTwoCompatClasses could not be loaded from path %@", compatPath] userInfo:nil];
552                        }
553                }
554                //ATV2.2
555                if([SapphireFrontRowCompat atvVersion] >= SapphireFrontRowCompatATVVersion2Dot2)
556                {
557                        compatPath = [frameworkPath stringByAppendingPathComponent:@"SapphireTakeTwoPointTwoCompatClasses.framework"];
558                        compat = [NSBundle bundleWithPath:compatPath];
559                        if( ![compat load]){ 
560                                @throw [NSException exceptionWithName:@"FileNotFoundException" reason:[NSString stringWithFormat:@"SapphireTakeTwoPointTwoCompatClasses could not be loaded from path %@", compatPath] userInfo:nil];
561                        }
562                }
563        }
564        else
565        {
566                //Check to see if we are later and mark it in preferences
567                NSBundle *loadedBundle = [NSBundle bundleForClass:NSClassFromString(@"SapphireFrontRowCompat")];
568                NSString *loadedVersion = [loadedBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
569                NSString *myVersion = [compat objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
570               
571                if([loadedVersion compare:myVersion] == NSOrderedAscending)
572                {
573                        //Check the one in the prefs too
574                        NSBundle *otherBundle = [NSBundle bundleWithPath:(NSString *)loadPath];
575                        NSString *otherVersion = [otherBundle objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey];
576                        if(otherVersion == nil || [otherVersion compare:myVersion] == NSOrderedAscending)
577                        {
578                                CFPreferencesSetAppValue(loadPathKey, (CFStringRef)compatPath, preferencesDomain);
579                                CFPreferencesAppSynchronize(preferencesDomain);
580                                //Likely need to restart Finder here (delayed) or something because the next time around, the newer framework will be loaded.
581                        }
582                }
583        }
584        if(loadPathProperty)
585                CFRelease(loadPathProperty);
586}
587
Note: See TracBrowser for help on using the repository browser.