diff options
Diffstat (limited to 'webrtc/base/macutils.cc')
-rw-r--r-- | webrtc/base/macutils.cc | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/webrtc/base/macutils.cc b/webrtc/base/macutils.cc new file mode 100644 index 0000000000..6e436d4a80 --- /dev/null +++ b/webrtc/base/macutils.cc @@ -0,0 +1,221 @@ +/* + * Copyright 2007 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <sstream> + +#include "webrtc/base/common.h" +#include "webrtc/base/logging.h" +#include "webrtc/base/macutils.h" +#include "webrtc/base/scoped_ptr.h" +#include "webrtc/base/stringutils.h" + +namespace rtc { + +/////////////////////////////////////////////////////////////////////////////// + +bool ToUtf8(const CFStringRef str16, std::string* str8) { + if ((NULL == str16) || (NULL == str8)) { + return false; + } + size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16), + kCFStringEncodingUTF8) + 1; + scoped_ptr<char[]> buffer(new char[maxlen]); + if (!buffer || !CFStringGetCString(str16, buffer.get(), maxlen, + kCFStringEncodingUTF8)) { + return false; + } + str8->assign(buffer.get()); + return true; +} + +bool ToUtf16(const std::string& str8, CFStringRef* str16) { + if (NULL == str16) { + return false; + } + *str16 = CFStringCreateWithBytes(kCFAllocatorDefault, + reinterpret_cast<const UInt8*>(str8.data()), + str8.length(), kCFStringEncodingUTF8, + false); + return NULL != *str16; +} + +#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) +void DecodeFourChar(UInt32 fc, std::string* out) { + std::stringstream ss; + ss << '\''; + bool printable = true; + for (int i = 3; i >= 0; --i) { + char ch = (fc >> (8 * i)) & 0xFF; + if (isprint(static_cast<unsigned char>(ch))) { + ss << ch; + } else { + printable = false; + break; + } + } + if (printable) { + ss << '\''; + } else { + ss.str(""); + ss << "0x" << std::hex << fc; + } + out->append(ss.str()); +} + +static bool GetGestalt(OSType ostype, int* value) { + ASSERT(NULL != value); + SInt32 native_value; + OSStatus result = Gestalt(ostype, &native_value); + if (noErr == result) { + *value = native_value; + return true; + } + std::string str; + DecodeFourChar(ostype, &str); + LOG_E(LS_ERROR, OS, result) << "Gestalt(" << str << ")"; + return false; +} + +bool GetOSVersion(int* major, int* minor, int* bugfix) { + ASSERT(major && minor && bugfix); + if (!GetGestalt(gestaltSystemVersion, major)) { + return false; + } + if (*major < 0x1040) { + *bugfix = *major & 0xF; + *minor = (*major >> 4) & 0xF; + *major = (*major >> 8); + return true; + } + return GetGestalt(gestaltSystemVersionMajor, major) && + GetGestalt(gestaltSystemVersionMinor, minor) && + GetGestalt(gestaltSystemVersionBugFix, bugfix); +} + +MacOSVersionName GetOSVersionName() { + int major = 0, minor = 0, bugfix = 0; + if (!GetOSVersion(&major, &minor, &bugfix)) { + return kMacOSUnknown; + } + if (major > 10) { + return kMacOSNewer; + } + if ((major < 10) || (minor < 3)) { + return kMacOSOlder; + } + switch (minor) { + case 3: + return kMacOSPanther; + case 4: + return kMacOSTiger; + case 5: + return kMacOSLeopard; + case 6: + return kMacOSSnowLeopard; + case 7: + return kMacOSLion; + case 8: + return kMacOSMountainLion; + case 9: + return kMacOSMavericks; + } + return kMacOSNewer; +} + +bool GetQuickTimeVersion(std::string* out) { + int ver; + if (!GetGestalt(gestaltQuickTimeVersion, &ver)) { + return false; + } + + std::stringstream ss; + ss << std::hex << ver; + *out = ss.str(); + return true; +} + +bool RunAppleScript(const std::string& script) { + // TODO(thaloun): Add a .mm file that contains something like this: + // NSString source from script + // NSAppleScript* appleScript = [[NSAppleScript alloc] initWithSource:&source] + // if (appleScript != nil) { + // [appleScript executeAndReturnError:nil] + // [appleScript release] +#ifndef CARBON_DEPRECATED + ComponentInstance component = NULL; + AEDesc script_desc; + AEDesc result_data; + OSStatus err; + OSAID script_id, result_id; + + AECreateDesc(typeNull, NULL, 0, &script_desc); + AECreateDesc(typeNull, NULL, 0, &result_data); + script_id = kOSANullScript; + result_id = kOSANullScript; + + component = OpenDefaultComponent(kOSAComponentType, typeAppleScript); + if (component == NULL) { + LOG(LS_ERROR) << "Failed opening Apple Script component"; + return false; + } + err = AECreateDesc(typeUTF8Text, script.data(), script.size(), &script_desc); + if (err != noErr) { + CloseComponent(component); + LOG(LS_ERROR) << "Failed creating Apple Script description"; + return false; + } + + err = OSACompile(component, &script_desc, kOSAModeCanInteract, &script_id); + if (err != noErr) { + AEDisposeDesc(&script_desc); + if (script_id != kOSANullScript) { + OSADispose(component, script_id); + } + CloseComponent(component); + LOG(LS_ERROR) << "Error compiling Apple Script"; + return false; + } + + err = OSAExecute(component, script_id, kOSANullScript, kOSAModeCanInteract, + &result_id); + + if (err == errOSAScriptError) { + LOG(LS_ERROR) << "Error when executing Apple Script: " << script; + AECreateDesc(typeNull, NULL, 0, &result_data); + OSAScriptError(component, kOSAErrorMessage, typeChar, &result_data); + int len = AEGetDescDataSize(&result_data); + char* data = (char*) malloc(len); + if (data != NULL) { + err = AEGetDescData(&result_data, data, len); + LOG(LS_ERROR) << "Script error: " << data; + } + AEDisposeDesc(&script_desc); + AEDisposeDesc(&result_data); + return false; + } + AEDisposeDesc(&script_desc); + if (script_id != kOSANullScript) { + OSADispose(component, script_id); + } + if (result_id != kOSANullScript) { + OSADispose(component, result_id); + } + CloseComponent(component); + return true; +#else + // TODO(thaloun): Support applescripts with the NSAppleScript API. + return false; +#endif // CARBON_DEPRECATED +} +#endif // WEBRTC_MAC && !defined(WEBRTC_IOS) + +/////////////////////////////////////////////////////////////////////////////// + +} // namespace rtc |