예제 #1
0
CFUserNotificationRef CFUserNotificationCreate(CFAllocatorRef allocator, CFTimeInterval timeout, CFOptionFlags flags, SInt32 *error, CFDictionaryRef dictionary) {
    CHECK_FOR_FORK();
    CFUserNotificationRef userNotification = NULL;
    SInt32 retval = ERR_SUCCESS;
    static uint16_t tokenCounter = 0;
    SInt32 token = ((getpid() << 16) | (tokenCounter++));
    CFStringRef sessionID = (dictionary ? CFDictionaryGetValue(dictionary, kCFUserNotificationSessionIDKey) : NULL);
    mach_port_t replyPort = MACH_PORT_NULL;

    if (!allocator) allocator = __CFGetDefaultAllocator();
    retval = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &replyPort);
    if (ERR_SUCCESS == retval && MACH_PORT_NULL != replyPort) retval = _CFUserNotificationSendRequest(allocator, sessionID, replyPort, token, timeout, flags, dictionary);
    if (ERR_SUCCESS == retval) {
        userNotification = (CFUserNotificationRef)_CFRuntimeCreateInstance(allocator, CFUserNotificationGetTypeID(), sizeof(struct __CFUserNotification) - sizeof(CFRuntimeBase), NULL);
        if (userNotification) {
            userNotification->_replyPort = replyPort;
            userNotification->_token = token;
            userNotification->_timeout = timeout;
            userNotification->_requestFlags = flags;
            userNotification->_responseFlags = 0;
            userNotification->_sessionID = NULL;
            userNotification->_responseDictionary = NULL;
            userNotification->_machPort = NULL;
            userNotification->_callout = NULL;
            if (sessionID) userNotification->_sessionID = CFStringCreateCopy(allocator, sessionID);
        } else {
            retval = unix_err(ENOMEM);
        }
    } else {
        if (dictionary) CFUserNotificationLog(CFDictionaryGetValue(dictionary, kCFUserNotificationAlertHeaderKey), CFDictionaryGetValue(dictionary, kCFUserNotificationAlertMessageKey));
    }
    if (ERR_SUCCESS != retval && MACH_PORT_NULL != replyPort) mach_port_destroy(mach_task_self(), replyPort);
    if (error) *error = retval;
    return userNotification;
}
예제 #2
0
CF_EXPORT SInt32 CFUserNotificationDisplayAlert(CFTimeInterval timeout, CFOptionFlags flags, CFURLRef iconURL, CFURLRef soundURL, CFURLRef localizationURL, CFStringRef alertHeader, CFStringRef alertMessage, CFStringRef defaultButtonTitle, CFStringRef alternateButtonTitle, CFStringRef otherButtonTitle, CFOptionFlags *responseFlags) {
    CHECK_FOR_FORK();
    CFUserNotificationRef userNotification;
    SInt32 retval = ERR_SUCCESS;
    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (iconURL) CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, iconURL);
    if (soundURL) CFDictionaryAddValue(dict, kCFUserNotificationSoundURLKey, soundURL);
    if (localizationURL) CFDictionaryAddValue(dict, kCFUserNotificationLocalizationURLKey, localizationURL);
    if (alertHeader) CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, alertHeader);
    if (alertMessage) CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, alertMessage);
    if (defaultButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationDefaultButtonTitleKey, defaultButtonTitle);
    if (alternateButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationAlternateButtonTitleKey, alternateButtonTitle);
    if (otherButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationOtherButtonTitleKey, otherButtonTitle);
    userNotification = CFUserNotificationCreate(kCFAllocatorSystemDefault, timeout, flags, &retval, dict);
    if (userNotification) {
        retval = CFUserNotificationReceiveResponse(userNotification, timeout, responseFlags);
        if (MACH_RCV_TIMED_OUT == retval) {
            retval = CFUserNotificationCancel(userNotification);
            if (responseFlags) *responseFlags = kCFUserNotificationCancelResponse;
        }
        CFRelease(userNotification);
    }
    CFRelease(dict);
    return retval;
}
SInt32 CFUserNotificationCancel(CFUserNotificationRef userNotification) {
    CHECK_FOR_FORK();
    SInt32 retval = ERR_SUCCESS;
#if DEPLOYMENT_TARGET_MACOSX
    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, 0, kCFUserNotificationCancelFlag, NULL);
#endif
    return retval;
}
SInt32 CFUserNotificationUpdate(CFUserNotificationRef userNotification, CFTimeInterval timeout, CFOptionFlags flags, CFDictionaryRef dictionary) {
    CHECK_FOR_FORK();
    SInt32 retval = ERR_SUCCESS;
#if DEPLOYMENT_TARGET_MACOSX
    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) retval = _CFUserNotificationSendRequest(CFGetAllocator(userNotification), userNotification->_sessionID, userNotification->_replyPort, userNotification->_token, timeout, flags|kCFUserNotificationUpdateFlag, dictionary);
#endif
    return retval;
}
예제 #5
0
CFRunLoopSourceRef CFUserNotificationCreateRunLoopSource(CFAllocatorRef allocator, CFUserNotificationRef userNotification, CFUserNotificationCallBack callout, CFIndex order) {
    CHECK_FOR_FORK();
    CFRunLoopSourceRef source = NULL;
    if (userNotification && callout && !userNotification->_machPort && MACH_PORT_NULL != userNotification->_replyPort) {
        CFMachPortContext context = {0, userNotification, NULL, NULL, NULL};
        userNotification->_machPort = CFMachPortCreateWithPort(CFGetAllocator(userNotification), (mach_port_t)userNotification->_replyPort, _CFUserNotificationMachPortCallBack, &context, NULL);
    }
    if (userNotification && userNotification->_machPort) {
        source = CFMachPortCreateRunLoopSource(allocator, userNotification->_machPort, order);
        userNotification->_callout = callout;
    }
    return source;
}
예제 #6
0
CFStringRef CFUserNotificationGetResponseValue(CFUserNotificationRef userNotification, CFStringRef key, CFIndex idx) {
    CHECK_FOR_FORK();
    CFStringRef retval = NULL;
    CFTypeRef value = NULL;
    if (userNotification && userNotification->_responseDictionary) {
        value = CFDictionaryGetValue(userNotification->_responseDictionary, key);
        if (CFGetTypeID(value) == CFStringGetTypeID()) {
            if (0 == idx) retval = (CFStringRef)value;
        } else if (CFGetTypeID(value) == CFArrayGetTypeID()) {
            if (0 <= idx && idx < CFArrayGetCount((CFArrayRef)value)) retval = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)value, idx);
        }
    }
    return retval;
}
예제 #7
0
SInt32 CFUserNotificationDisplayNotice(CFTimeInterval timeout, CFOptionFlags flags, CFURLRef iconURL, CFURLRef soundURL, CFURLRef localizationURL, CFStringRef alertHeader, CFStringRef alertMessage, CFStringRef defaultButtonTitle) {
    CHECK_FOR_FORK();
    CFUserNotificationRef userNotification;
    SInt32 retval = ERR_SUCCESS;
    CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorSystemDefault, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (iconURL) CFDictionaryAddValue(dict, kCFUserNotificationIconURLKey, iconURL);
    if (soundURL) CFDictionaryAddValue(dict, kCFUserNotificationSoundURLKey, soundURL);
    if (localizationURL) CFDictionaryAddValue(dict, kCFUserNotificationLocalizationURLKey, localizationURL);
    if (alertHeader) CFDictionaryAddValue(dict, kCFUserNotificationAlertHeaderKey, alertHeader);
    if (alertMessage) CFDictionaryAddValue(dict, kCFUserNotificationAlertMessageKey, alertMessage);
    if (defaultButtonTitle) CFDictionaryAddValue(dict, kCFUserNotificationDefaultButtonTitleKey, defaultButtonTitle);
    userNotification = CFUserNotificationCreate(kCFAllocatorSystemDefault, timeout, flags, &retval, dict);
    if (userNotification) CFRelease(userNotification);
    CFRelease(dict);
    return retval;
}
SInt32 CFUserNotificationReceiveResponse(CFUserNotificationRef userNotification, CFTimeInterval timeout, CFOptionFlags *responseFlags) {
    CHECK_FOR_FORK();
    SInt32 retval = ERR_SUCCESS;
#if DEPLOYMENT_TARGET_MACOSX
    mach_msg_timeout_t msgtime = (timeout > 0.0 && 1000.0 * timeout < INT_MAX) ? (mach_msg_timeout_t)(1000.0 * timeout) : 0;
    mach_msg_base_t *msg = NULL;
    CFIndex size = MAX_STRING_COUNT * MAX_STRING_LENGTH;
    CFDataRef responseData;
    
    if (userNotification && MACH_PORT_NULL != userNotification->_replyPort) {
        msg = (mach_msg_base_t *)CFAllocatorAllocate(kCFAllocatorSystemDefault, size, 0);
	if (__CFOASafe) __CFSetLastAllocationEventName(msg, "CFUserNotification (temp)");
        if (msg) {
            memset(msg, 0, size);
            msg->header.msgh_size = size;
            if (msgtime > 0) {
                retval = mach_msg((mach_msg_header_t *)msg, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, size, userNotification->_replyPort, msgtime, MACH_PORT_NULL);
            } else {
                retval = mach_msg((mach_msg_header_t *)msg, MACH_RCV_MSG, 0, size, userNotification->_replyPort, 0, MACH_PORT_NULL);
            }
            if (ERR_SUCCESS == retval) {
                if (responseFlags) *responseFlags = msg->header.msgh_id;
                if (msg->header.msgh_size > sizeof(mach_msg_base_t)) {
                    responseData = CFDataCreate(kCFAllocatorSystemDefault, (uint8_t *)msg + sizeof(mach_msg_base_t), msg->header.msgh_size - sizeof(mach_msg_base_t));
                    if (responseData) {
                        userNotification->_responseDictionary = CFPropertyListCreateFromXMLData(kCFAllocatorSystemDefault, responseData, kCFPropertyListImmutable, NULL);
                        CFRelease(responseData);
                    }
                }
                if (userNotification->_machPort) {
                    CFMachPortInvalidate(userNotification->_machPort);
                    CFRelease(userNotification->_machPort);
                    userNotification->_machPort = NULL;
                }
                mach_port_destroy(mach_task_self(), userNotification->_replyPort);
                userNotification->_replyPort = MACH_PORT_NULL;
            }
            CFAllocatorDeallocate(kCFAllocatorSystemDefault, msg);
        } else {
            retval = unix_err(ENOMEM);
        }
    }
#endif
    return retval;
}
예제 #9
0
CFDictionaryRef CFUserNotificationGetResponseDictionary(CFUserNotificationRef userNotification) {
    CHECK_FOR_FORK();
    return userNotification ? userNotification->_responseDictionary : NULL;
}