Add zalsa configure flag, enabled by default if possible
[jack2.git] / android / JackAndroidSemaphore.cpp
blob703e289c54d1770b2cd10df0af60faa302c03636
1 /*
2 Copyright (C) 2004-2008 Grame
3 Copyright (C) 2013 Samsung Electronics
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include "JackAndroidSemaphore.h"
22 #include "JackTools.h"
23 #include "JackConstants.h"
24 #include "JackError.h"
25 #include <fcntl.h>
26 #include <stdio.h>
27 #include <sys/time.h>
28 #include "IAndroidShm.h"
29 #include "shm.h"
30 #include "android/Shm.h" //android extension of shm.h
32 namespace Jack
35 pthread_mutex_t JackAndroidSemaphore::mutex = PTHREAD_MUTEX_INITIALIZER;
37 void JackAndroidSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
39 char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
40 JackTools::RewriteName(client_name, ext_client_name);
41 if (getenv("JACK_PROMISCUOUS_SERVER")) {
42 snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name);
43 } else {
44 snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
48 bool JackAndroidSemaphore::Signal()
50 int res;
52 if (!fSemaphore) {
53 jack_error("JackAndroidSemaphore::Signal name = %s already deallocated!!", fName);
54 return false;
57 if (fFlush)
58 return true;
60 if ((res = sem_post(fSemaphore)) != 0) {
61 jack_error("JackAndroidSemaphore::Signal name = %s err = %s", fName, strerror(errno));
63 return (res == 0);
66 bool JackAndroidSemaphore::SignalAll()
68 int res;
70 if (!fSemaphore) {
71 jack_error("JackAndroidSemaphore::SignalAll name = %s already deallocated!!", fName);
72 return false;
75 if (fFlush)
76 return true;
78 if ((res = sem_post(fSemaphore)) != 0) {
79 jack_error("JackAndroidSemaphore::SignalAll name = %s err = %s", fName, strerror(errno));
81 return (res == 0);
85 bool JackAndroidSemaphore::Wait()
87 int res;
89 if (!fSemaphore) {
90 jack_error("JackAndroidSemaphore::Wait name = %s already deallocated!!", fName);
91 return false;
94 if ((res = sem_wait(fSemaphore)) != 0) {
95 jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
97 return (res == 0);
101 bool JackAndroidSemaphore::Wait()
103 int res;
105 while ((res = sem_wait(fSemaphore) < 0)) {
106 jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
107 if (errno != EINTR) {
108 break;
111 return (res == 0);
114 bool JackAndroidSemaphore::TimedWait(long usec)
116 int res;
117 struct timeval now;
118 timespec time;
120 if (!fSemaphore) {
121 jack_error("JackAndroidSemaphore::TimedWait name = %s already deallocated!!", fName);
122 return false;
124 gettimeofday(&now, 0);
125 time.tv_sec = now.tv_sec + usec / 1000000;
126 long tv_usec = (now.tv_usec + (usec % 1000000));
127 time.tv_sec += tv_usec / 1000000;
128 time.tv_nsec = (tv_usec % 1000000) * 1000;
130 while ((res = sem_timedwait(fSemaphore, &time)) < 0) {
131 jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
132 jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
133 jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
134 if (errno == ETIMEDOUT) {
135 timespec ts;
136 clock_gettime(CLOCK_REALTIME, &ts);
137 ts.tv_sec = time.tv_sec - ts.tv_sec;
138 ts.tv_nsec = time.tv_nsec - ts.tv_nsec;
139 if (ts.tv_nsec < 0) {
140 ts.tv_nsec += 1000000000;
141 ts.tv_sec -= 1;
143 if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
144 jack_error("JackAndroidSemaphore::TimedWait time may changed or client killed already! wait again!");
145 gettimeofday(&now, 0);
146 time.tv_sec = now.tv_sec + usec / 1000000;
147 long tv_usec = (now.tv_usec + (usec % 1000000));
148 time.tv_sec += tv_usec / 1000000;
149 time.tv_nsec = (tv_usec % 1000000) * 1000;
150 if ((res = sem_timedwait(fSemaphore, &time)) < 0) {
151 jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
152 jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
153 jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
157 if (errno != EINTR) {
158 break;
161 return (res == 0);
164 // Server side : publish the semaphore in the global namespace
165 bool JackAndroidSemaphore::Allocate(const char* name, const char* server_name, int value)
167 pthread_mutex_lock (&mutex);
168 BuildName(name, server_name, fName, sizeof(fName));
169 jack_log("JackAndroidSemaphore::Allocate name = %s val = %ld", fName, value);
171 android::sp<android::IAndroidShm> service = android::Shm::getShmService();
172 if(service == NULL){
173 jack_error("shm service is null");
174 return false;
176 fSemaphoreMemory = service->InitSemaphore(fName);
177 if(fSemaphoreMemory != NULL){
178 fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
181 if(fSemaphore == NULL) {
182 jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno));
183 pthread_mutex_unlock (&mutex);
184 return false;
185 } else {
186 sem_init(fSemaphore, 1, 0);
187 jack_log("sem_init()");
188 pthread_mutex_unlock (&mutex);
189 return true;
193 // Client side : get the published semaphore from server
194 bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name)
196 pthread_mutex_lock (&mutex);
197 BuildName(name, server_name, fName, sizeof(fName));
198 jack_log("JackAndroidSemaphore::Connect name = %s", fName);
200 // Temporary...
201 if (fSemaphore) {
202 jack_log("Already connected name = %s", name);
203 pthread_mutex_unlock (&mutex);
204 return true;
207 android::sp<android::IAndroidShm> service = android::Shm::getShmService();
208 if(service == NULL){
209 jack_error("shm service is null");
210 return false;
213 fSemaphoreMemory = service->InitSemaphore(fName);
214 if(fSemaphoreMemory != NULL){
215 fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
218 if(fSemaphore == NULL) {
219 jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno));
220 pthread_mutex_unlock (&mutex);
221 return false;
222 } else {
223 int val = 0;
224 sem_getvalue(fSemaphore, &val);
225 jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val);
226 pthread_mutex_unlock (&mutex);
227 return true;
231 bool JackAndroidSemaphore::Connect(const char* name, const char* server_name)
233 return ConnectInput(name, server_name);
236 bool JackAndroidSemaphore::ConnectOutput(const char* name, const char* server_name)
238 return ConnectInput(name, server_name);
241 bool JackAndroidSemaphore::Disconnect()
243 if (fSemaphore) {
244 jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
245 fSemaphore = NULL;
247 return true;
250 // Server side : destroy the semaphore
251 void JackAndroidSemaphore::Destroy()
253 if (fSemaphore != NULL) {
254 jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
255 fSemaphore = NULL;
256 } else {
257 jack_error("JackAndroidSemaphore::Destroy semaphore == NULL");
261 } // end of namespace