1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/modules/audio_device/android/low_latency_event.h"
12
13 #include <assert.h>
14
15 #define HANDLE_EINTR(x) ({ \
16 typeof(x) eintr_wrapper_result; \
17 do { \
18 eintr_wrapper_result = (x); \
19 } while (eintr_wrapper_result == -1 && errno == EINTR); \
20 eintr_wrapper_result; \
21 })
22
23 #define IGNORE_EINTR(x) ({ \
24 typeof(x) eintr_wrapper_result; \
25 do { \
26 eintr_wrapper_result = (x); \
27 if (eintr_wrapper_result == -1 && errno == EINTR) { \
28 eintr_wrapper_result = 0; \
29 } \
30 } while (0); \
31 eintr_wrapper_result; \
32 })
33
34 namespace webrtc {
35
36 const LowLatencyEvent::Handle LowLatencyEvent::kInvalidHandle = -1;
37 const int LowLatencyEvent::kReadHandle = 0;
38 const int LowLatencyEvent::kWriteHandle = 1;
39
LowLatencyEvent()40 LowLatencyEvent::LowLatencyEvent() {
41 handles_[kReadHandle] = kInvalidHandle;
42 handles_[kWriteHandle] = kInvalidHandle;
43 }
44
~LowLatencyEvent()45 LowLatencyEvent::~LowLatencyEvent() {
46 Stop();
47 }
48
Start()49 bool LowLatencyEvent::Start() {
50 assert(handles_[kReadHandle] == kInvalidHandle);
51 assert(handles_[kWriteHandle] == kInvalidHandle);
52
53 return socketpair(AF_UNIX, SOCK_STREAM, 0, handles_) == 0;
54 }
55
Stop()56 bool LowLatencyEvent::Stop() {
57 bool ret = Close(&handles_[kReadHandle]) && Close(&handles_[kWriteHandle]);
58 handles_[kReadHandle] = kInvalidHandle;
59 handles_[kWriteHandle] = kInvalidHandle;
60 return ret;
61 }
62
SignalEvent(int event_id,int event_msg)63 void LowLatencyEvent::SignalEvent(int event_id, int event_msg) {
64 WriteFd(event_id, event_msg);
65 }
66
WaitOnEvent(int * event_id,int * event_msg)67 void LowLatencyEvent::WaitOnEvent(int* event_id, int* event_msg) {
68 ReadFd(event_id, event_msg);
69 }
70
Close(Handle * handle)71 bool LowLatencyEvent::Close(Handle* handle) {
72 if (*handle == kInvalidHandle) {
73 return false;
74 }
75 int retval = IGNORE_EINTR(close(*handle));
76 *handle = kInvalidHandle;
77 return retval == 0;
78 }
79
WriteFd(int message_id,int message)80 void LowLatencyEvent::WriteFd(int message_id, int message) {
81 char buffer[sizeof(message_id) + sizeof(message)];
82 size_t bytes = sizeof(buffer);
83 memcpy(buffer, &message_id, sizeof(message_id));
84 memcpy(&buffer[sizeof(message_id)], &message, sizeof(message));
85 ssize_t bytes_written = HANDLE_EINTR(write(handles_[kWriteHandle], buffer,
86 bytes));
87 if (bytes_written != static_cast<ssize_t>(bytes)) {
88 assert(false);
89 }
90 }
91
ReadFd(int * message_id,int * message)92 void LowLatencyEvent::ReadFd(int* message_id, int* message) {
93 char buffer[sizeof(message_id) + sizeof(message)];
94 size_t bytes = sizeof(buffer);
95 ssize_t bytes_read = HANDLE_EINTR(read(handles_[kReadHandle], buffer, bytes));
96 if (bytes_read == 0) {
97 *message_id = 0;
98 *message = 0;
99 return;
100 } else if (bytes_read == static_cast<ssize_t>(bytes)) {
101 memcpy(message_id, buffer, sizeof(*message_id));
102 memcpy(message, &buffer[sizeof(*message_id)], sizeof(*message));
103 } else {
104 assert(false);
105 }
106 }
107
108 } // namespace webrtc
109