예제 #1
0
파일: hid.c 프로젝트: CShark/usbdmx
static void *read_thread(void *param)
{
	hid_device *dev = param;
	SInt32 code;

	/* Move the device's run loop to this thread. */
	IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode);

	/* Create the RunLoopSource which is used to signal the
	   event loop to stop when hid_close() is called. */
	CFRunLoopSourceContext ctx;
	memset(&ctx, 0, sizeof(ctx));
	ctx.version = 0;
	ctx.info = dev;
	ctx.perform = &perform_signal_callback;
	dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx);
	CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode);

	/* Store off the Run Loop so it can be stopped from hid_close()
	   and on device disconnection. */
	dev->run_loop = CFRunLoopGetCurrent();

	/* Notify the main thread that the read thread is up and running. */
	pthread_barrier_wait(&dev->barrier);

	/* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input
	   reports into the hid_report_callback(). */
	while (!dev->shutdown_thread && !dev->disconnected) {
		code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE);
		/* Return if the device has been disconnected */
		if (code == kCFRunLoopRunFinished) {
			dev->disconnected = 1;
			break;
		}


		/* Break if The Run Loop returns Finished or Stopped. */
		if (code != kCFRunLoopRunTimedOut &&
		    code != kCFRunLoopRunHandledSource) {
			/* There was some kind of error. Setting
			   shutdown seems to make sense, but
			   there may be something else more appropriate */
			dev->shutdown_thread = 1;
			break;
		}
	}

	/* Now that the read thread is stopping, Wake any threads which are
	   waiting on data (in hid_read_timeout()). Do this under a mutex to
	   make sure that a thread which is about to go to sleep waiting on
	   the condition acutally will go to sleep before the condition is
	   signaled. */
	pthread_mutex_lock(&dev->mutex);
	pthread_cond_broadcast(&dev->condition);
	pthread_mutex_unlock(&dev->mutex);

	/* Wait here until hid_close() is called and makes it past
	   the call to CFRunLoopWakeUp(). This thread still needs to
	   be valid when that function is called on the other thread. */
	pthread_barrier_wait(&dev->shutdown_barrier);

	return NULL;
}
mailstream_low * mailstream_low_cfstream_open_voip_timeout(const char * hostname, int16_t port,
  int voip_enabled, time_t timeout)
{
#if HAVE_CFNETWORK
  mailstream_low * s;
  struct mailstream_cfstream_data * cfstream_data;
  CFReadStreamRef readStream;
  CFWriteStreamRef writeStream;
  CFStringRef hostString;
  CFOptionFlags readFlags;
  CFOptionFlags writeFlags;
  int r;
  
  hostString = CFStringCreateWithCString(NULL, hostname, kCFStringEncodingUTF8);
  CFStreamCreatePairWithSocketToHost(NULL, hostString, port, &readStream, &writeStream);
  CFRelease(hostString);

#if TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR  
  if (voip_enabled) {
    CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
    CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  }
#endif
  
  cfstream_data = cfstream_data_new(readStream, writeStream);
  s = mailstream_low_new(cfstream_data, mailstream_cfstream_driver);
	mailstream_low_set_timeout(s, timeout);  

  //fprintf(stderr, "open %s %i -> %p\n", hostname, port, s);
  
  /* setup streams */
  cfstream_data->streamContext.info = s;
  
  readFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventHasBytesAvailable |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  writeFlags = kCFStreamEventOpenCompleted |
  kCFStreamEventCanAcceptBytes |
  kCFStreamEventErrorOccurred |
  kCFStreamEventEndEncountered;
  
  CFReadStreamSetClient(cfstream_data->readStream, readFlags, readStreamCallback, &cfstream_data->streamContext);
  CFWriteStreamSetClient(cfstream_data->writeStream, writeFlags, writeStreamCallback, &cfstream_data->streamContext);
  
  CFRelease(readStream);
  CFRelease(writeStream);
  readStream = NULL;
  writeStream = NULL;
  
  /* setup cancel */
  cfstream_data->cancelContext.info = s;
  cfstream_data->cancelContext.perform = cancelPerform;
  cfstream_data->cancelSource = CFRunLoopSourceCreate(NULL, 0, &cfstream_data->cancelContext);
  
  r = low_open(s);
  if (r < 0) {
    mailstream_low_cfstream_close(s);
    return NULL;
  }
  
  return s;
#else
  return NULL;
#endif
}
예제 #3
0
파일: app.cpp 프로젝트: gitrider/wxsj2
bool wxApp::Initialize(int& argc, wxChar **argv)
{
    // Mac-specific

#if __WXDEBUG__
    InstallDebugAssertOutputHandler ( NewDebugAssertOutputHandlerUPP( wxMacAssertOutputHandler ) );
#endif
    UMAInitToolbox( 4, sm_isEmbedded ) ;
    SetEventMask( everyEvent ) ;
    UMAShowWatchCursor() ;

#ifndef __DARWIN__
#  if __option(profile)
    ProfilerInit( collectDetailed, bestTimeBase , 40000 , 50 ) ;
#  endif
#endif

#ifndef __DARWIN__
    // now avoid exceptions thrown for new (bad_alloc)
    // FIXME CS for some changes outside wxMac does not compile anymore
#if 0
    std::__throws_bad_alloc = 0 ;
#endif

#endif

    s_macCursorRgn = ::NewRgn() ;

    // Mac OS X passes a process serial number command line argument when
    // the application is launched from the Finder. This argument must be
    // removed from the command line arguments before being handled by the
    // application (otherwise applications would need to handle it)
    if ( argc > 1 )
    {
        static const wxChar *ARG_PSN = _T("-psn_");
        if ( wxStrncmp(argv[1], ARG_PSN, wxStrlen(ARG_PSN)) == 0 )
        {
            // remove this argument
            --argc;
            memmove(argv + 1, argv + 2, argc * sizeof(char *));
        }
    }

    if ( !wxAppBase::Initialize(argc, argv) )
        return false;

#if wxUSE_INTL
    wxFont::SetDefaultEncoding(wxLocale::GetSystemEncoding());
#endif

#if TARGET_API_MAC_OSX
    // these might be the startup dirs, set them to the 'usual' dir containing the app bundle
    wxString startupCwd = wxGetCwd() ;
    if ( startupCwd == wxT("/") || startupCwd.Right(15) == wxT("/Contents/MacOS") )
    {
        CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle() ) ;
        CFURLRef urlParent = CFURLCreateCopyDeletingLastPathComponent( kCFAllocatorDefault , url ) ;
        CFRelease( url ) ;
        CFStringRef path = CFURLCopyFileSystemPath ( urlParent , kCFURLPOSIXPathStyle ) ;
        CFRelease( urlParent ) ;
        wxString cwd = wxMacCFStringHolder(path).AsString(wxLocale::GetSystemEncoding());       
        wxSetWorkingDirectory( cwd ) ;
    }
#endif

    wxMacCreateNotifierTable() ;

#ifdef __WXMAC_OSX__
    /* connect posted events to common-mode run loop so that wxPostEvent events
       are handled even while we're in the menu or on a scrollbar */
    CFRunLoopSourceContext event_posted_context = {0};
    event_posted_context.perform = macPostedEventCallback;
    m_macEventPosted = CFRunLoopSourceCreate(NULL,0,&event_posted_context);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), m_macEventPosted, kCFRunLoopCommonModes);
#endif

    UMAShowArrowCursor() ;

    return true;
}
예제 #4
0
int DeviceManagerThread::Run()
{

    SetThreadName("OVR::DeviceManagerThread");
    LogText("OVR::DeviceManagerThread - running (ThreadId=0x%p).\n", GetThreadId());

    // Store out the run loop ref.
    RunLoop = CFRunLoopGetCurrent();

    // Create a 'source' to enable us to signal the run loop to process the command queue.
    CFRunLoopSourceContext sourceContext;
    memset(&sourceContext, 0, sizeof(sourceContext));
    sourceContext.version = 0;
    sourceContext.info = this;
    sourceContext.perform = &staticCommandQueueSourceCallback;

    CommandQueueSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0 , &sourceContext);

    CFRunLoopAddSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode);


    // Signal to the parent thread that initialization has finished.
    StartupEvent.SetEvent();


    ThreadCommand::PopBuffer command;
   
    while(!IsExiting())
    {
        // PopCommand will reset event on empty queue.
        if (PopCommand(&command))
        {
            command.Execute();
        }
        else
        {
            SInt32 exitReason = 0;
            do {

                UInt32 waitMs = INT_MAX;

                // If devices have time-dependent logic registered, get the longest wait
                // allowed based on current ticks.
                if (!TicksNotifiers.IsEmpty())
                {
                    UInt64 ticksMks = Timer::GetTicks();
                    UInt32  waitAllowed;

                    for (UPInt j = 0; j < TicksNotifiers.GetSize(); j++)
                    {
                        waitAllowed = (UInt32)(TicksNotifiers[j]->OnTicks(ticksMks) / Timer::MksPerMs);
                        if (waitAllowed < waitMs)
                            waitMs = waitAllowed;
                    }
                }
                
                // Enter blocking run loop. We may continue until we timeout in which
                // case it's time to service the ticks. Or if commands arrive in the command
                // queue then the source callback will call 'CFRunLoopStop' causing this
                // to return.
                CFTimeInterval blockInterval = 0.001 * (double) waitMs;
                exitReason = CFRunLoopRunInMode(kCFRunLoopDefaultMode, blockInterval, false);

                if (exitReason == kCFRunLoopRunFinished)
                {
                    // Maybe this will occur during shutdown?
                    break;
                }
                else if (exitReason == kCFRunLoopRunStopped )
                {
                    // Commands need processing or we're being shutdown.
                    break;
                }
                else if (exitReason == kCFRunLoopRunTimedOut)
                {
                    // Timed out so that we can service our ticks callbacks.
                    continue;
                }
                else if (exitReason == kCFRunLoopRunHandledSource)
                {
                    // Should never occur since the last param when we call
                    // 'CFRunLoopRunInMode' is false.
                    OVR_ASSERT(false);
                    break;
                }
                else
                {
                    OVR_ASSERT_LOG(false, ("CFRunLoopRunInMode returned unexpected code"));
                    break;
                }
            }
            while(true);                    
        }
    }

                                   
    CFRunLoopRemoveSource(RunLoop, CommandQueueSource, kCFRunLoopDefaultMode);
    CFRelease(CommandQueueSource);
    
    LogText("OVR::DeviceManagerThread - exiting (ThreadId=0x%p).\n", GetThreadId());

    return 0;
}
예제 #5
0
/* CF_EXPORT */ void
CFNetServiceBrowserStopSearch(CFNetServiceBrowserRef b, CFStreamError* error) {

	__CFNetServiceBrowser* browser = (__CFNetServiceBrowser*)b;

	// By default, the error is marked as a cancel
	CFStreamError extra = {kCFStreamErrorDomainNetServices , kCFNetServicesErrorCancel};

	// Make sure error has a value.
	if (!error)
		error = &extra;

	// Lock down the browser
	__CFSpinLock(&(browser->_lock));

	// Make sure there is something to cancel.
	if (browser->_trigger) {

		CFRunLoopSourceContext ctxt = {
			0,									// version
			browser,							// info
			NULL,								// retain
			NULL,								// release
			NULL,								// copyDescription
			NULL,								// equal
			NULL,								// hash
			NULL,								// schedule
			NULL,								// cancel
			(void(*)(void*))(&_BrowserCancel)  // perform
		};

		// Remove the trigger from run loops and modes
		_CFTypeUnscheduleFromMultipleRunLoops(browser->_trigger, browser->_schedules);

		// Go ahead and invalidate the trigger
		_CFTypeInvalidate(browser->_trigger);

		// Release the trigger now.
		CFRelease(browser->_trigger);

		// Need to clean up the service discovery stuff if there is
		if (browser->_browse) {

			// Release the underlying service discovery reference
			DNSServiceRefDeallocate(browser->_browse);
			browser->_browse = NULL;

			// Dump all the lists of items.
			CFDictionaryRemoveAllValues(browser->_found);
			CFArrayRemoveAllValues(browser->_adds);
			CFArrayRemoveAllValues(browser->_removes);
		}

		// Copy the error into place
		memmove(&(browser->_error), error, sizeof(error[0]));

		// Create the cancel source
		browser->_trigger = CFRunLoopSourceCreate(CFGetAllocator(browser), 0, &ctxt);

		// If the cancel was created, need to schedule and signal it.
		if (browser->_trigger) {

			CFArrayRef schedules = browser->_schedules;
			CFIndex i, count = CFArrayGetCount(schedules);

			// Schedule the new trigger
			_CFTypeScheduleOnMultipleRunLoops(browser->_trigger, schedules);

			// Signal the cancel for immediate attention.
			CFRunLoopSourceSignal((CFRunLoopSourceRef)(browser->_trigger));

			// Make sure the signal can make it through
			for (i = 0; i < count; i += 2) {

				// Grab the run loop for checking
				CFRunLoopRef runloop = (CFRunLoopRef)CFArrayGetValueAtIndex(schedules, i);

				// If it's sleeping, need to further check it.
				if (CFRunLoopIsWaiting(runloop)) {

					// Grab the mode for further check
					CFStringRef mode = CFRunLoopCopyCurrentMode(runloop);

					if (mode) {

						// If the trigger is in the right mode, need to wake up the run loop.
						if (CFRunLoopContainsSource(runloop, (CFRunLoopSourceRef)(browser->_trigger), mode)) {
							CFRunLoopWakeUp(runloop);
						}

						// Don't need this anymore.
						CFRelease(mode);
					}
				}
			}
		}
	}

	// Unlock the browser
	__CFSpinUnlock(&(browser->_lock));
}