source: trunk/CommonMediaPlayer/Classes/CMPPlayerManager.h @ 1195

Revision 1195, 9.4 KB checked in by lechium, 4 years ago (diff)

oops duplicate var

Line 
1/*
2 * CMPPlayerManager.h
3 * CommonMediaPlayer
4 *
5 * Created by Graham Booker on Feb. 1 2010
6 * Copyright 2010 Common Media Player
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 * Lesser General Public License as published by the Free Software Foundation; either version 3 of the
11 * License, 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 Lesser
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License along with this program; if
18 * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 */
21
22#import <Security/Security.h>
23#import "CMPTypesDefines.h"
24
25#include <sys/mount.h>
26
27@protocol CMPPlayerController, CMPPlayer;
28
29@interface CMPPlayerManager : NSObject {
30        NSMutableSet                    *knownPlayers;
31        NSMutableSet                    *knownControllers;
32        NSMutableDictionary             *playersForTypes;       //Keys are types, values are dictionaries.  Resulting dictionaries are keyed by extension, default keyed by @"", values are NSArrays of classes which can handle this.
33}
34
35+ (CMPPlayerManager *)sharedPlayerManager;
36+ (int)version;
37+ (int)apiVersion;
38
39//types is a dictionary with the key being the type above, and value is an array of extensions (empty array means any extension)
40- (void)registerPlayer:(Class)player forTypes:(NSDictionary *)types;
41- (void)registerPlayer:(Class)player forType:(CMPPlayerManagerFileType)type withExtensions:(NSArray *)extensions;
42//preferences are same formate as playersForTypes listed above
43- (id <CMPPlayer>)playerForPath:(NSString *)path type:(CMPPlayerManagerFileType)type preferences:(NSDictionary *)preferences;
44- (id <CMPPlayerController>)playerControllerForPlayer:(id <CMPPlayer>)player scene:(BRRenderScene *)scene preferences:(NSDictionary *)preferences;
45
46@end
47
48#ifdef FrameworkLoadDebug
49#define FrameworkLoadPrint(...) NSLog(__VA_ARGS__)
50#else
51#define FrameworkLoadPrint(...)
52#endif
53
54static inline BOOL needCopy(NSString *frameworkPath)
55{
56        NSFileManager *fm = [NSFileManager defaultManager];
57        BOOL isDir = NO;
58        FrameworkLoadPrint(@"Checking if dir exists");
59        if(![fm fileExistsAtPath:frameworkPath isDirectory:&isDir] || !isDir)
60                return YES;
61       
62        NSBundle *bundle = [NSBundle bundleWithPath:frameworkPath];
63        NSString *plistPath = [bundle pathForResource:@"Info" ofType:@"plist"];
64        NSDictionary *plist = [NSDictionary dictionaryWithContentsOfFile:plistPath];
65       
66        NSString *version = [plist objectForKey:@"CFBundleVersion"];
67        FrameworkLoadPrint(@"Version is %@:%d compared to %d", version, [version intValue], CMPVersion);
68        if([version intValue] < CMPVersion)
69                return YES;
70       
71        return NO;
72}
73
74static BOOL createDirectoryTree(NSFileManager *fm, NSString *directory)
75{
76        BOOL isDir;
77        if([fm fileExistsAtPath:directory isDirectory:&isDir] && isDir)
78                return YES;
79        if(!createDirectoryTree(fm, [directory stringByDeletingLastPathComponent]))
80           return NO;
81        return [fm createDirectoryAtPath:directory attributes:nil];
82}
83
84static inline BOOL installPassthroughComponent(NSFileManager *fm, NSString *passPath)
85{
86        //We have a copy, must have had permission to distribute it
87        struct statfs slashStat;
88        if(statfs("/", &slashStat) == -1)
89                return NO;
90       
91        BOOL success = YES;
92        int status;
93        AuthorizationItem authItems[2] = {
94                {kAuthorizationEnvironmentUsername, strlen("frontrow"), "frontrow", 0},
95                {kAuthorizationEnvironmentPassword, strlen("frontrow"), "frontrow", 0},
96        };
97        AuthorizationEnvironment environ = {2, authItems};
98        AuthorizationItem rightSet[] = {{kAuthorizationRightExecute, 0, NULL, 0}};
99        AuthorizationRights rights = {1, rightSet};
100        AuthorizationRef auth;
101        OSStatus result = AuthorizationCreate(&rights, &environ, kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights, &auth);
102        if(result == errAuthorizationSuccess)
103        {
104                BOOL readonly = slashStat.f_flags & MNT_RDONLY;
105               
106                if(readonly)
107                {
108                        char *command = "mount -uw /";
109                        char *arguments[] = {"-c", command, NULL};
110                        result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
111                        wait(&status);
112                        FrameworkLoadPrint(@"Set to read-write with status %d", status);
113                }
114               
115                NSString *passDest = @"/Library/Audio/Plug-Ins/HAL/";
116                int status = 0;
117                if (![fm fileExistsAtPath:passDest])
118                {
119                        char *command = "mkdir -p \"$HALPATH\"";
120                        setenv("HALPATH", [passDest fileSystemRepresentation], 1);
121                        char *arguments[] = {"-c", command, NULL};
122                        result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
123                        wait(&status);
124                        unsetenv("HALPATH");
125                        FrameworkLoadPrint(@"Created HAL path with status %d", status);
126                }
127                NSString *existingPath = [passDest stringByAppendingPathComponent:@"AC3PassthroughDevice.plugin"];
128
129                if([fm fileExistsAtPath:existingPath])
130                {
131                        char *command = "rm -Rf \"$EXISTING\"";
132                        setenv("EXISTING", [existingPath fileSystemRepresentation], 1);
133                        char *arguments[] = {"-c", command, NULL};
134                        result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
135                        wait(&status);
136                        unsetenv("EXISTING");
137                        FrameworkLoadPrint(@"Removed existing with status %d", status);
138                }
139                char *command = "cp -R \"$PASSPATH\" \"$PASSDEST\"";
140                setenv("PASSPATH", [passPath fileSystemRepresentation], 1);
141                setenv("PASSDEST", [passDest fileSystemRepresentation], 1);
142                char *arguments[] = {"-c", command, NULL};
143                result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
144                wait(&status);
145                unsetenv("PASSPATH");
146                unsetenv("PASSDEST");
147               
148                if(readonly)
149                {
150                        char *command = "mount -ur /";
151                        char *arguments[] = {"-c", command, NULL};
152                        result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
153                        wait(&status);
154                        FrameworkLoadPrint(@"Set to read-only with status %d", status);
155                }
156        }
157        if(result != errAuthorizationSuccess)
158        {
159                success = NO;
160                FrameworkLoadPrint(@"Failed to install Passthrough component");
161        }
162        AuthorizationFree(auth, kAuthorizationFlagDefaults);
163        return success;
164}
165
166static inline BOOL loadCMPFramework(NSString *frapPath)
167{
168        NSString *frameworkPath = [NSHomeDirectory() stringByAppendingPathComponent:@"Library/Frameworks/CommonMediaPlayer.framework"];
169        FrameworkLoadPrint(@"Path is at %@", frameworkPath);
170#ifdef FrameworkAlwaysCopy
171        BOOL neededCopy = YES;
172#else
173        BOOL neededCopy = needCopy(frameworkPath);
174#endif
175        FrameworkLoadPrint(@"Need copy is %d", neededCopy);
176        if(neededCopy)
177        {
178                NSFileManager *fm = [NSFileManager defaultManager];
179                NSString *frameworkInFrap = [frapPath stringByAppendingPathComponent:@"Contents/Frameworks/CommonMediaPlayer.framework"];
180                FrameworkLoadPrint(@"Going to copy %@", frameworkInFrap);
181                BOOL success = [fm removeFileAtPath:frameworkPath handler:nil];
182                FrameworkLoadPrint(@"Delete success is %d", success);
183                success = YES;
184                NSString *frameworksDir = [frameworkPath stringByDeletingLastPathComponent];
185                BOOL isDir;
186                if([fm fileExistsAtPath:frameworksDir isDirectory:&isDir] && isDir)
187                {
188                        //Check permissions
189                        NSDictionary *attributes = [fm fileAttributesAtPath:frameworksDir traverseLink:YES];
190                        if([[attributes objectForKey:NSFileOwnerAccountID] intValue] == 0)
191                        {
192                                //Owned by root
193                                AuthorizationItem authItems[2] = {
194                                        {kAuthorizationEnvironmentUsername, strlen("frontrow"), "frontrow", 0},
195                                        {kAuthorizationEnvironmentPassword, strlen("frontrow"), "frontrow", 0},
196                                };
197                                AuthorizationEnvironment environ = {2, authItems};
198                                AuthorizationItem rightSet[] = {{kAuthorizationRightExecute, 0, NULL, 0}};
199                                AuthorizationRights rights = {1, rightSet};
200                                AuthorizationRef auth;
201                                OSStatus result = AuthorizationCreate(&rights, &environ, kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights, &auth);
202                                if(result == errAuthorizationSuccess)
203                                {
204                                        char *command = "chown frontrow \"$FWDIR\"";
205                                        setenv("FWDIR", [frameworksDir fileSystemRepresentation], 1);
206                                        char *arguments[] = {"-c", command, NULL};
207                                        result = AuthorizationExecuteWithPrivileges(auth, "/bin/sh", kAuthorizationFlagDefaults, arguments, NULL);
208                                        unsetenv("FWDIR");
209                                }
210                                if(result != errAuthorizationSuccess)
211                                {
212                                        success = NO;
213                                        FrameworkLoadPrint(@"Failed to correct permissions on Frameworks directory");
214                                }
215                                AuthorizationFree(auth, kAuthorizationFlagDefaults);
216                                int status;
217                                wait(&status);
218                        }
219                }
220                else
221                        success = createDirectoryTree(fm, frameworksDir);
222                FrameworkLoadPrint(@"Creation of dir is %d", success);
223                success = [fm copyPath:frameworkInFrap toPath:frameworkPath handler:nil];
224                FrameworkLoadPrint(@"Copy success is %d", success);
225                //Check if we were allowed to distribute the passthrough component
226                NSString *passPath = [frameworkPath stringByAppendingPathComponent:@"Resources/AC3PassthroughDevice.plugin"];
227                if([fm fileExistsAtPath:passPath])
228                        installPassthroughComponent(fm, passPath);
229                if(!success || needCopy(frameworkPath))
230                        //We failed in our copy too!
231                        return NO;
232        }
233       
234        NSBundle *framework = [NSBundle bundleWithPath:frameworkPath];
235        FrameworkLoadPrint(@"Bundle is %@", framework);
236        if([framework isLoaded] && neededCopy)
237        {
238                //We should restart here
239                FrameworkLoadPrint(@"Need to restart");
240                [[NSApplication sharedApplication] terminate:nil];
241        }
242       
243        FrameworkLoadPrint(@"Loading framework");
244        return [framework load];
245}
Note: See TracBrowser for help on using the repository browser.