00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #if !defined LL_DARWIN
00035 #error "Use only with Mac OS X"
00036 #endif
00037
00038 #include "llappviewermacosx.h"
00039 #include "llcommandlineparser.h"
00040
00041 #include "llmemtype.h"
00042
00043 #include "llviewernetwork.h"
00044 #include "llviewercontrol.h"
00045 #include "llmd5.h"
00046 #include "llurlsimstring.h"
00047 #include "llfloaterworldmap.h"
00048 #include "llurldispatcher.h"
00049 #include <Carbon/Carbon.h>
00050 #include "lldir.h"
00051 namespace
00052 {
00053
00054
00055 int gArgC;
00056 char** gArgV;
00057 }
00058
00059 int main( int argc, char **argv )
00060 {
00061 LLMemType mt1(LLMemType::MTYPE_STARTUP);
00062
00063 #if LL_SOLARIS && defined(__sparc)
00064 asm ("ta\t6");
00065 #endif
00066
00067
00068 (void) chdir(gDirUtilp->getAppRODataDir().c_str());
00069
00070 LLAppViewerMacOSX* viewer_app_ptr = new LLAppViewerMacOSX();
00071
00072 viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
00073
00074
00075 gArgC = argc;
00076 gArgV = argv;
00077
00078 bool ok = viewer_app_ptr->init();
00079 if(!ok)
00080 {
00081 llwarns << "Application init failed." << llendl;
00082 return -1;
00083 }
00084
00085
00086 if(!LLApp::isQuitting())
00087 {
00088 viewer_app_ptr->mainLoop();
00089 }
00090
00091 if (!LLApp::isError())
00092 {
00093
00094
00095
00096
00097
00098 viewer_app_ptr->cleanup();
00099 }
00100 delete viewer_app_ptr;
00101 viewer_app_ptr = NULL;
00102 return 0;
00103 }
00104
00105 LLAppViewerMacOSX::LLAppViewerMacOSX()
00106 {
00107 }
00108
00109 LLAppViewerMacOSX::~LLAppViewerMacOSX()
00110 {
00111 }
00112
00113 bool LLAppViewerMacOSX::init()
00114 {
00115 return LLAppViewer::init();
00116 }
00117
00118
00119
00120
00121
00122 std::pair<std::string, std::string> parse_psn(const std::string& s)
00123 {
00124 if (s.find("-psn_") == 0)
00125 {
00126
00127
00128 return std::make_pair("psn", s.substr(5));
00129 }
00130 else
00131 {
00132 return std::make_pair(std::string(), std::string());
00133 }
00134 }
00135
00136 bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp)
00137 {
00138
00139 clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number");
00140 clp.setCustomParser(parse_psn);
00141
00142
00143 if(clp.parseCommandLine(gArgC, gArgV) == false)
00144 {
00145 return false;
00146 }
00147
00148
00149
00150
00151 const char* filename = "arguments.txt";
00152 llifstream ifs(filename, llifstream::binary);
00153 if (!ifs.is_open())
00154 {
00155 llwarns << "Unable to open file" << filename << llendl;
00156 return false;
00157 }
00158
00159 if(clp.parseCommandLineFile(ifs) == false)
00160 {
00161 return false;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 CFURLRef url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("language"), CFSTR("txt"), NULL);
00173 char path[MAX_PATH];
00174 if(CFURLGetFileSystemRepresentation(url, false, (UInt8 *)path, sizeof(path)))
00175 {
00176 LLString lang;
00177 if(_read_file_into_string(lang, path))
00178 {
00179 LLControlVariable* c = gSavedSettings.getControl("SystemLanguage");
00180 if(c)
00181 {
00182 c->setValue(lang, false);
00183 }
00184 }
00185 }
00186 CFRelease(url);
00187
00188 return true;
00189 }
00190
00191 void LLAppViewerMacOSX::handleSyncCrashTrace()
00192 {
00193
00194 }
00195
00196 void LLAppViewerMacOSX::handleCrashReporting()
00197 {
00198
00199 LLString command_str;
00200 command_str += "open crashreporter.app";
00201
00202 clear_signals();
00203 llinfos << "Launching crash reporter using: '" << command_str << "'" << llendl;
00204 system(command_str.c_str());
00205 llinfos << "returned from crash reporter... dying" << llendl;
00206 _exit(1);
00207 }
00208
00209 std::string LLAppViewerMacOSX::generateSerialNumber()
00210 {
00211 char serial_md5[MD5HEX_STR_SIZE];
00212 serial_md5[0] = 0;
00213
00214
00215 CFStringRef serialNumber = NULL;
00216 io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
00217 IOServiceMatching("IOPlatformExpertDevice"));
00218 if (platformExpert) {
00219 serialNumber = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
00220 CFSTR(kIOPlatformSerialNumberKey),
00221 kCFAllocatorDefault, 0);
00222 IOObjectRelease(platformExpert);
00223 }
00224
00225 if (serialNumber)
00226 {
00227 char buffer[MAX_STRING];
00228 if (CFStringGetCString(serialNumber, buffer, MAX_STRING, kCFStringEncodingASCII))
00229 {
00230 LLMD5 md5( (unsigned char*)buffer );
00231 md5.hex_digest(serial_md5);
00232 }
00233 CFRelease(serialNumber);
00234 }
00235
00236 return serial_md5;
00237 }
00238
00239 OSErr AEGURLHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
00240 {
00241 OSErr result = noErr;
00242 DescType actualType;
00243 char buffer[1024];
00244 Size size;
00245
00246 result = AEGetParamPtr (
00247 messagein,
00248 keyDirectObject,
00249 typeCString,
00250 &actualType,
00251 (Ptr)buffer,
00252 sizeof(buffer),
00253 &size);
00254
00255 if(result == noErr)
00256 {
00257 std::string url = buffer;
00258 const bool from_external_browser = true;
00259 LLURLDispatcher::dispatch(url, from_external_browser);
00260 }
00261
00262 return(result);
00263 }
00264
00265 OSErr AEQuitHandler(const AppleEvent *messagein, AppleEvent *reply, long refIn)
00266 {
00267 OSErr result = noErr;
00268
00269 LLAppViewer::instance()->userQuit();
00270
00271 return(result);
00272 }
00273
00274 OSStatus simpleDialogHandler(EventHandlerCallRef handler, EventRef event, void *userdata)
00275 {
00276 OSStatus result = eventNotHandledErr;
00277 OSStatus err;
00278 UInt32 evtClass = GetEventClass(event);
00279 UInt32 evtKind = GetEventKind(event);
00280 WindowRef window = (WindowRef)userdata;
00281
00282 if((evtClass == kEventClassCommand) && (evtKind == kEventCommandProcess))
00283 {
00284 HICommand cmd;
00285 err = GetEventParameter(event, kEventParamDirectObject, typeHICommand, NULL, sizeof(cmd), NULL, &cmd);
00286
00287 if(err == noErr)
00288 {
00289 switch(cmd.commandID)
00290 {
00291 case kHICommandOK:
00292 QuitAppModalLoopForWindow(window);
00293 result = noErr;
00294 break;
00295
00296 case kHICommandCancel:
00297 QuitAppModalLoopForWindow(window);
00298 result = userCanceledErr;
00299 break;
00300 }
00301 }
00302 }
00303
00304 return(result);
00305 }
00306
00307 OSStatus DisplayReleaseNotes(void)
00308 {
00309 OSStatus err;
00310 IBNibRef nib = NULL;
00311 WindowRef window = NULL;
00312
00313 err = CreateNibReference(CFSTR("SecondLife"), &nib);
00314
00315 if(err == noErr)
00316 {
00317 CreateWindowFromNib(nib, CFSTR("Release Notes"), &window);
00318 }
00319
00320 if(err == noErr)
00321 {
00322
00323 HIViewRef textView;
00324 ControlID id;
00325
00326 id.signature = 'text';
00327 id.id = 0;
00328
00329 LLString releaseNotesText;
00330
00331 _read_file_into_string(releaseNotesText, "releasenotes.txt");
00332
00333 err = HIViewFindByID(HIViewGetRoot(window), id, &textView);
00334
00335 if(err == noErr)
00336 {
00337
00338 CFStringRef str = CFStringCreateWithBytes(
00339 NULL,
00340 (const UInt8*)releaseNotesText.c_str(),
00341 releaseNotesText.size(),
00342 kCFStringEncodingWindowsLatin1,
00343 FALSE);
00344
00345 if(str != NULL)
00346 {
00347 int size = CFStringGetLength(str);
00348
00349 if(size > 0)
00350 {
00351 UniChar *chars = new UniChar[size + 1];
00352 CFStringGetCharacters(str, CFRangeMake(0, size), chars);
00353
00354 err = TXNSetData(HITextViewGetTXNObject(textView), kTXNUnicodeTextData, chars, size * sizeof(UniChar), kTXNStartOffset, kTXNStartOffset);
00355
00356 delete[] chars;
00357 }
00358
00359 CFRelease(str);
00360 }
00361 else
00362 {
00363
00364 err = TXNSetData(HITextViewGetTXNObject(textView), kTXNTextData, releaseNotesText.c_str(), releaseNotesText.size(), kTXNStartOffset, kTXNStartOffset);
00365 }
00366 }
00367
00368
00369 if(err == noErr)
00370 {
00371 err = TXNSetSelection(HITextViewGetTXNObject(textView), kTXNStartOffset, kTXNStartOffset);
00372 }
00373
00374 if(err == noErr)
00375 {
00376
00377 TXNShowSelection(HITextViewGetTXNObject(textView), false);
00378 }
00379 }
00380
00381 if(err == noErr)
00382 {
00383 ShowWindow(window);
00384 }
00385
00386 if(err == noErr)
00387 {
00388
00389 EventHandlerRef handler = NULL;
00390 EventTypeSpec handlerEvents[] =
00391 {
00392 { kEventClassCommand, kEventCommandProcess }
00393 };
00394
00395 InstallWindowEventHandler(
00396 window,
00397 NewEventHandlerUPP(simpleDialogHandler),
00398 GetEventTypeCount (handlerEvents),
00399 handlerEvents,
00400 (void*)window,
00401 &handler);
00402 }
00403
00404 if(err == noErr)
00405 {
00406 RunAppModalLoopForWindow(window);
00407 }
00408
00409 if(window != NULL)
00410 {
00411 DisposeWindow(window);
00412 }
00413
00414 if(nib != NULL)
00415 {
00416 DisposeNibReference(nib);
00417 }
00418
00419 return(err);
00420 }
00421
00422 void init_apple_menu(const char* product)
00423 {
00424
00425 {
00426 OSStatus err;
00427 IBNibRef nib = NULL;
00428
00429 err = CreateNibReference(CFSTR("SecondLife"), &nib);
00430
00431 if(err == noErr)
00432 {
00433
00434 SetMenuBarFromNib(nib, CFSTR("MenuBar"));
00435 }
00436
00437 if(nib != NULL)
00438 {
00439 DisposeNibReference(nib);
00440 }
00441 }
00442
00443
00444
00445 if(AEInstallEventHandler('GURL', 'GURL', NewAEEventHandlerUPP(AEGURLHandler),0, false) != noErr)
00446 {
00447
00448 llinfos << "Couldn't install 'GURL' AppleEvent handler. Continuing..." << llendl;
00449 }
00450
00451
00452 if(AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP(AEQuitHandler),0, false) != noErr)
00453 {
00454
00455 llinfos << "Couldn't install Quit AppleEvent handler. Continuing..." << llendl;
00456 }
00457 }