Index: webrtc/base/macsocketserver.cc |
diff --git a/webrtc/base/macsocketserver.cc b/webrtc/base/macsocketserver.cc |
index b763e813b037d94909d8263d01049b4dcd5e0008..96b2091dd37b38dfd30745ecb7d9c67c768d0867 100644 |
--- a/webrtc/base/macsocketserver.cc |
+++ b/webrtc/base/macsocketserver.cc |
@@ -212,4 +212,175 @@ |
ASSERT(run_loop_ == CFRunLoopGetCurrent()); |
CFRunLoopStop(run_loop_); |
} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// MacCarbonSocketServer |
+/////////////////////////////////////////////////////////////////////////////// |
+#ifndef CARBON_DEPRECATED |
+ |
+const UInt32 kEventClassSocketServer = 'MCSS'; |
+const UInt32 kEventWakeUp = 'WAKE'; |
+const EventTypeSpec kEventWakeUpSpec[] = { |
+ { kEventClassSocketServer, kEventWakeUp } |
+}; |
+ |
+std::string DecodeEvent(EventRef event) { |
+ std::string str; |
+ DecodeFourChar(::GetEventClass(event), &str); |
+ str.push_back(':'); |
+ DecodeFourChar(::GetEventKind(event), &str); |
+ return str; |
+} |
+ |
+MacCarbonSocketServer::MacCarbonSocketServer() |
+ : event_queue_(GetCurrentEventQueue()), wake_up_(NULL) { |
+ VERIFY(noErr == CreateEvent(NULL, kEventClassSocketServer, kEventWakeUp, 0, |
+ kEventAttributeUserEvent, &wake_up_)); |
+} |
+ |
+MacCarbonSocketServer::~MacCarbonSocketServer() { |
+ if (wake_up_) { |
+ ReleaseEvent(wake_up_); |
+ } |
+} |
+ |
+bool MacCarbonSocketServer::Wait(int cms, bool process_io) { |
+ ASSERT(GetCurrentEventQueue() == event_queue_); |
+ |
+ // Listen to all events if we're processing I/O. |
+ // Only listen for our wakeup event if we're not. |
+ UInt32 num_types = 0; |
+ const EventTypeSpec* events = NULL; |
+ if (!process_io) { |
+ num_types = GetEventTypeCount(kEventWakeUpSpec); |
+ events = kEventWakeUpSpec; |
+ } |
+ |
+ EventTargetRef target = GetEventDispatcherTarget(); |
+ EventTimeout timeout = |
+ (kForever == cms) ? kEventDurationForever : cms / 1000.0; |
+ EventTimeout end_time = GetCurrentEventTime() + timeout; |
+ |
+ bool done = false; |
+ while (!done) { |
+ EventRef event; |
+ OSStatus result = ReceiveNextEvent(num_types, events, timeout, true, |
+ &event); |
+ if (noErr == result) { |
+ if (wake_up_ != event) { |
+ LOG_F(LS_VERBOSE) << "Dispatching event: " << DecodeEvent(event); |
+ result = SendEventToEventTarget(event, target); |
+ if ((noErr != result) && (eventNotHandledErr != result)) { |
+ LOG_E(LS_ERROR, OS, result) << "SendEventToEventTarget"; |
+ } |
+ } else { |
+ done = true; |
+ } |
+ ReleaseEvent(event); |
+ } else if (eventLoopTimedOutErr == result) { |
+ ASSERT(cms != kForever); |
+ done = true; |
+ } else if (eventLoopQuitErr == result) { |
+ // Ignore this... we get spurious quits for a variety of reasons. |
+ LOG_E(LS_VERBOSE, OS, result) << "ReceiveNextEvent"; |
+ } else { |
+ // Some strange error occurred. Log it. |
+ LOG_E(LS_WARNING, OS, result) << "ReceiveNextEvent"; |
+ return false; |
+ } |
+ if (kForever != cms) { |
+ timeout = end_time - GetCurrentEventTime(); |
+ } |
+ } |
+ return true; |
+} |
+ |
+void MacCarbonSocketServer::WakeUp() { |
+ if (!IsEventInQueue(event_queue_, wake_up_)) { |
+ RetainEvent(wake_up_); |
+ OSStatus result = PostEventToQueue(event_queue_, wake_up_, |
+ kEventPriorityStandard); |
+ if (noErr != result) { |
+ LOG_E(LS_ERROR, OS, result) << "PostEventToQueue"; |
+ } |
+ } |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+// MacCarbonAppSocketServer |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+MacCarbonAppSocketServer::MacCarbonAppSocketServer() |
+ : event_queue_(GetCurrentEventQueue()) { |
+ // Install event handler |
+ VERIFY(noErr == InstallApplicationEventHandler( |
+ NewEventHandlerUPP(WakeUpEventHandler), 1, kEventWakeUpSpec, this, |
+ &event_handler_)); |
+ |
+ // Install a timer and set it idle to begin with. |
+ VERIFY(noErr == InstallEventLoopTimer(GetMainEventLoop(), |
+ kEventDurationForever, |
+ kEventDurationForever, |
+ NewEventLoopTimerUPP(TimerHandler), |
+ this, |
+ &timer_)); |
+} |
+ |
+MacCarbonAppSocketServer::~MacCarbonAppSocketServer() { |
+ RemoveEventLoopTimer(timer_); |
+ RemoveEventHandler(event_handler_); |
+} |
+ |
+OSStatus MacCarbonAppSocketServer::WakeUpEventHandler( |
+ EventHandlerCallRef next, EventRef event, void *data) { |
+ QuitApplicationEventLoop(); |
+ return noErr; |
+} |
+ |
+void MacCarbonAppSocketServer::TimerHandler( |
+ EventLoopTimerRef timer, void *data) { |
+ QuitApplicationEventLoop(); |
+} |
+ |
+bool MacCarbonAppSocketServer::Wait(int cms, bool process_io) { |
+ if (!process_io && cms == 0) { |
+ // No op. |
+ return true; |
+ } |
+ if (kForever != cms) { |
+ // Start a timer. |
+ OSStatus error = |
+ SetEventLoopTimerNextFireTime(timer_, cms / 1000.0); |
+ if (error != noErr) { |
+ LOG(LS_ERROR) << "Failed setting next fire time."; |
+ } |
+ } |
+ if (!process_io) { |
+ // No way to listen to common modes and not get socket events, unless |
+ // we disable each one's callbacks. |
+ EnableSocketCallbacks(false); |
+ } |
+ RunApplicationEventLoop(); |
+ if (!process_io) { |
+ // Reenable them. Hopefully this won't cause spurious callbacks or |
+ // missing ones while they were disabled. |
+ EnableSocketCallbacks(true); |
+ } |
+ return true; |
+} |
+ |
+void MacCarbonAppSocketServer::WakeUp() { |
+ // TODO: No-op if there's already a WakeUp in flight. |
+ EventRef wake_up; |
+ VERIFY(noErr == CreateEvent(NULL, kEventClassSocketServer, kEventWakeUp, 0, |
+ kEventAttributeUserEvent, &wake_up)); |
+ OSStatus result = PostEventToQueue(event_queue_, wake_up, |
+ kEventPriorityStandard); |
+ if (noErr != result) { |
+ LOG_E(LS_ERROR, OS, result) << "PostEventToQueue"; |
+ } |
+ ReleaseEvent(wake_up); |
+} |
+ |
+#endif |
} // namespace rtc |