diff --git a/libs/driver/libetherdream/etherdream.c b/libs/driver/libetherdream/etherdream.c
index 90742a4..dacb93d 100755
--- a/libs/driver/libetherdream/etherdream.c
+++ b/libs/driver/libetherdream/etherdream.c
@@ -1,64 +1,50 @@
/* Ether Dream interface library
- *
- * Copyright 2011-2012 Jacob Potter
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of either the GNU General Public License version 2
- * or 3, or the GNU Lesser General Public License version 3, as published
- * by the Free Software Foundation, at your option.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
+*
+* Copyright 2011-2012 Jacob Potter
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of either the GNU General Public License version 2
+* or 3, or the GNU Lesser General Public License version 3, as published
+* by the Free Software Foundation, at your option.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+*/
#include "etherdream.h"
-
-
-static FILE *trace_fp = NULL;
-#if __MACH__
-static long long timer_start, timer_freq_numer, timer_freq_denom;
-#else
-static struct timespec start_time;
-#endif
-static pthread_mutex_t dac_list_lock;
-static struct etherdream *dac_list = NULL;
+static FILE* trace_fp = NULL;
+static std::mutex dac_list_lock;
+static struct etherdream* dac_list = NULL;
+static std::chrono::high_resolution_clock::time_point startTime = std::chrono::high_resolution_clock::now();
+static std::thread watcherThread;
/* microseconds()
- *
- * Return the number of microseconds since library initialization.
- */
+*
+* Return the number of microseconds since library initialization.
+*/
static long long microseconds(void) {
-#if __MACH__
- long long time_diff = mach_absolute_time() - timer_start;
- return time_diff * timer_freq_numer / timer_freq_denom;
-#else
- struct timespec t;
- clock_gettime(CLOCK_REALTIME, &t);
- return (t.tv_sec - start_time.tv_sec) * 1000000 +
- (t.tv_nsec - start_time.tv_nsec) / 1000;
-#endif
+ const auto upTime = std::chrono::high_resolution_clock::now() - startTime;
+ return std::chrono::duration_cast(upTime).count();
}
/* microsleep(us)
- *
- * Like usleep().
- */
+*
+* Like usleep().
+*/
static void microsleep(long long us) {
- nanosleep(&(struct timespec){ .tv_sec = us / 1000000,
- .tv_nsec = (us % 1000000) * 1000 }, NULL);
+ std::this_thread::sleep_for(std::chrono::microseconds(us));
}
/* trace(d, fmt, ...)
- *
- * Utility function for logging.
- */
-static void trace(struct etherdream *d, char *fmt, ...) {
+*
+* Utility function for logging.
+*/
+static void trace(struct etherdream* d, const char* fmt, ...) {
if (!trace_fp)
return;
@@ -83,27 +69,29 @@ static void trace(struct etherdream *d, char *fmt, ...) {
}
/* log_socket_error(d, call)
- *
- * Log an error in a socket call.
- */
-static void log_socket_error(struct etherdream *d, const char *call) {
+*
+* Log an error in a socket call.
+*/
+static void log_socket_error(struct etherdream* d, const char* call) {
trace(d, "!! socket error in %s: %d: %s\n",
call, errno, strerror(errno));
}
/* wait_for_fd_activity(d, usec, writable)
- *
- * Wait for activity (if writable is 0, then readable or error; if writable
- * is 1, then writable or error) on d's socket. Time out after usec. Returns
- * 1 if activity happened, 0 on timeout, -1 on error (will also log error).
- */
-static int wait_for_fd_activity(struct etherdream *d, int usec, int writable) {
+*
+* Wait for activity (if writable is 0, then readable or error; if writable
+* is 1, then writable or error) on d's socket. Time out after usec. Returns
+* 1 if activity happened, 0 on timeout, -1 on error (will also log error).
+*/
+static int wait_for_fd_activity(struct etherdream* d, int usec, int writable) {
fd_set set;
FD_ZERO(&set);
FD_SET(d->conn.dc_sock, &set);
+ struct timeval t;
+ t.tv_sec = usec / 1000000;
+ t.tv_usec = usec % 1000000;
int res = select(d->conn.dc_sock + 1, (writable ? NULL : &set),
- (writable ? &set : NULL), &set, &(struct timeval){
- .tv_sec = usec / 1000000, .tv_usec = usec % 1000000 });
+ (writable ? &set : NULL), &set, &t);
if (res < 0)
log_socket_error(d, "select");
@@ -111,11 +99,11 @@ static int wait_for_fd_activity(struct etherdream *d, int usec, int writable) {
}
/* read_bytes(d, buf, len)
- *
- * Read exactly len bytes from d's connection socket into buf. Returns 0 on
- * success, -1 on error (will also log error).
- */
-static int read_bytes(struct etherdream *d, char *buf, int len) {
+*
+* Read exactly len bytes from d's connection socket into buf. Returns 0 on
+* success, -1 on error (will also log error).
+*/
+static int read_bytes(struct etherdream* d, char* buf, int len) {
while (d->conn.dc_read_buf_size < len) {
int res = wait_for_fd_activity(d, DEFAULT_TIMEOUT, 0);
if (res < 0)
@@ -126,8 +114,8 @@ static int read_bytes(struct etherdream *d, char *buf, int len) {
}
res = recv(d->conn.dc_sock,
- d->conn.dc_read_buf + d->conn.dc_read_buf_size,
- len - d->conn.dc_read_buf_size, 0);
+ d->conn.dc_read_buf + d->conn.dc_read_buf_size,
+ len - d->conn.dc_read_buf_size, 0);
if (res <= 0) {
log_socket_error(d, "recv");
@@ -141,7 +129,7 @@ static int read_bytes(struct etherdream *d, char *buf, int len) {
if (d->conn.dc_read_buf_size > len) {
printf("moving %d up by %d\n", d->conn.dc_read_buf_size, len);
memmove(d->conn.dc_read_buf, d->conn.dc_read_buf + len,
- d->conn.dc_read_buf_size - len);
+ d->conn.dc_read_buf_size - len);
}
d->conn.dc_read_buf_size -= len;
@@ -149,11 +137,11 @@ static int read_bytes(struct etherdream *d, char *buf, int len) {
}
/* send_all(d, data, len)
- *
- * Send all of data to d's socket. Returns 0 on success, -1 on error or if the
- * send times out (will also log error).
- */
-static int send_all(struct etherdream *d, const char *data, int len) {
+*
+* Send all of data to d's socket. Returns 0 on success, -1 on error or if the
+* send times out (will also log error).
+*/
+static int send_all(struct etherdream* d, const char* data, int len) {
do {
int res = wait_for_fd_activity(d, 100000, 1);
if (res < 0)
@@ -177,12 +165,12 @@ static int send_all(struct etherdream *d, const char *data, int len) {
}
/* read_resp(d)
- *
- * Read a response from the DAC into d's conn.resp buffer. Returns 0 on
- * success, -1 on error (in which case the error will have been logged).
- */
-static int read_resp(struct etherdream *d) {
- int res = read_bytes(d, (char *)&d->conn.resp, sizeof(d->conn.resp));
+*
+* Read a response from the DAC into d's conn.resp buffer. Returns 0 on
+* success, -1 on error (in which case the error will have been logged).
+*/
+static int read_resp(struct etherdream* d) {
+ int res = read_bytes(d, (char*)&d->conn.resp, sizeof(d->conn.resp));
if (res < 0)
return res;
@@ -191,12 +179,12 @@ static int read_resp(struct etherdream *d) {
}
/* dump_resp(d)
- *
- * Dump the last response received from d.
- */
-static void dump_resp(struct etherdream *d) {
- struct etherdream_conn *conn = &d->conn;
- struct dac_status *st = &conn->resp.dac_status;
+*
+* Dump the last response received from d.
+*/
+static void dump_resp(struct etherdream* d) {
+ struct etherdream_conn* conn = &d->conn;
+ struct dac_status* st = &conn->resp.dac_status;
trace(d, "-- Protocol %d / LE %d / playback %d / source %d\n",
0 /* st->protocol */, st->light_engine_state,
st->playback_state, st->source);
@@ -208,86 +196,111 @@ static void dump_resp(struct etherdream *d) {
}
/* dac_connect(d, host, port)
- *
- * Initialize a dac's connection struct and open up a socket. On success,
- * return 0; otherwise, return -1.
- */
-static int dac_connect(struct etherdream *d) {
- struct etherdream_conn *conn = &d->conn;
- memset(conn, 0, sizeof *conn);
+*
+* Initialize a dac's connection struct and open up a socket. On success,
+* return 0; otherwise, return -1.
+*/
+static int dac_connect(struct etherdream* d) {
+ struct etherdream_conn* conn = &d->conn;
+ memset(conn, 0, sizeof * conn);
// Open socket
conn->dc_sock = socket(AF_INET, SOCK_STREAM, 0);
+
if (conn->dc_sock < 0) {
log_socket_error(d, "socket");
return -1;
}
- unsigned long nonblocking = 1;
- ioctl(conn->dc_sock, FIONBIO, &nonblocking);
+ u_long iMode = 1;
+#ifdef _MSC_VER
+ ioctlsocket(conn->dc_sock, FIONBIO, &iMode);
+#else
+ ioctl(conn->dc_sock, FIONBIO, &iMode);
+#endif
+
+ sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = d->addr.s_addr;
+ addr.sin_port = htons(7765);
- struct sockaddr_in addr = {
- .sin_family = AF_INET,
- .sin_addr.s_addr = d->addr.s_addr, .sin_port = htons(7765)
- };
+ connect(conn->dc_sock, (struct sockaddr*)&addr, (int)sizeof addr);
+#ifdef _MSC_VER
// Because the socket is nonblocking, this will always error...
- connect(conn->dc_sock, (struct sockaddr *)&addr, (int)sizeof addr);
+ if (WSAGetLastError() != WSAEWOULDBLOCK) {
+#else
if (errno != EINPROGRESS) {
+#endif
log_socket_error(d, "connect");
goto bail;
}
+
+
// Wait for connection to go through
- int res = wait_for_fd_activity(d, DEFAULT_TIMEOUT, 1);
- if (res < 0)
- goto bail;
- if (res == 0) {
- trace(d, "Connection to %s timed out.\n", inet_ntoa(d->addr));
- goto bail;
+ {
+ int res = wait_for_fd_activity(d, DEFAULT_TIMEOUT, 1);
+ if (res < 0)
+ goto bail;
+ if (res == 0) {
+ trace(d, "Connection to %s timed out.\n", inet_ntoa(d->addr));
+ goto bail;
+ }
}
// See if we have *actually* connected
- int error;
- unsigned int len = sizeof error;
- if (getsockopt(conn->dc_sock, SOL_SOCKET, SO_ERROR, (char *)&error,
- &len) < 0) {
- log_socket_error(d, "getsockopt");
- goto bail;
- }
+ {
+ int error;
+#ifdef _MSC_VER
+ int len = sizeof error;
+#else
+ unsigned int len = sizeof error;
+#endif
+ if (getsockopt(conn->dc_sock, SOL_SOCKET, SO_ERROR, (char*)&error,
+ &len) < 0) {
+ log_socket_error(d, "getsockopt");
+ goto bail;
+ }
- if (error) {
- errno = error;
- log_socket_error(d, "connect");
- goto bail;
+ if (error) {
+ errno = error;
+ log_socket_error(d, "connect");
+ goto bail;
+ }
}
- int ndelay = 1;
- if (setsockopt(conn->dc_sock, IPPROTO_TCP, TCP_NODELAY,
- (char *)&ndelay, sizeof(ndelay)) < 0) {
- log_socket_error(d, "setsockopt TCP_NODELAY");
- goto bail;
+ {
+ int ndelay = 1;
+ if (setsockopt(conn->dc_sock, IPPROTO_TCP, TCP_NODELAY,
+ (char*)&ndelay, sizeof(ndelay)) < 0) {
+ log_socket_error(d, "setsockopt TCP_NODELAY");
+ goto bail;
+ }
}
// After we connect, the DAC will send an initial status response
if (read_resp(d) < 0)
goto bail;
- char c = 'p';
- send_all(d, &c, 1);
+ {
+ char c = 'p';
+ send_all(d, &c, 1);
+ }
if (read_resp(d) < 0)
goto bail;
dump_resp(d);
if (d->sw_revision >= 2) {
- c = 'v';
+ char c = 'v';
if (send_all(d, &c, 1) < 0)
goto bail;
- res = read_bytes(d, d->version, sizeof(d->version));
+ int res = read_bytes(d, d->version, sizeof(d->version));
if (res < 0)
return res;
- } else {
+ }
+ else {
strcpy(d->version, "[old]");
}
@@ -295,17 +308,21 @@ static int dac_connect(struct etherdream *d) {
return 0;
bail:
+#ifdef _MSC_VER
+ closesocket(d->conn.dc_sock);
+#else
close(d->conn.dc_sock);
+#endif
return -1;
-}
+ }
/* check_data_response(d)
- *
- * Handle a response from d: update our record of the number of sent-but-not-
- * ACKed points, and error if the response was unexpected.
- */
-static int check_data_response(struct etherdream *d) {
- struct etherdream_conn *conn = &d->conn;
+*
+* Handle a response from d: update our record of the number of sent-but-not-
+* ACKed points, and error if the response was unexpected.
+*/
+static int check_data_response(struct etherdream* d) {
+ struct etherdream_conn* conn = &d->conn;
if (conn->resp.dac_status.playback_state == 0)
conn->dc_begin_sent = 0;
@@ -316,7 +333,8 @@ static int check_data_response(struct etherdream *d) {
}
conn->unacked_points -= conn->ackbuf[conn->ackbuf_cons];
conn->ackbuf_cons = (conn->ackbuf_cons + 1) % MAX_LATE_ACKS;
- } else {
+ }
+ else {
conn->pending_meta_acks--;
}
@@ -331,12 +349,12 @@ static int check_data_response(struct etherdream *d) {
}
/* dac_get_acks(d, wait)
- *
- * Read any ACKs we are owed, waiting up to 'wait' microseconds.
- */
-static int dac_get_acks(struct etherdream *d, int wait) {
+*
+* Read any ACKs we are owed, waiting up to 'wait' microseconds.
+*/
+static int dac_get_acks(struct etherdream* d, int wait) {
while (d->conn.pending_meta_acks
- || (d->conn.ackbuf_prod != d->conn.ackbuf_cons)) {
+ || (d->conn.ackbuf_prod != d->conn.ackbuf_cons)) {
int res = wait_for_fd_activity(d, wait, 0);
if (res <= 0)
return res;
@@ -349,14 +367,14 @@ static int dac_get_acks(struct etherdream *d, int wait) {
}
/* dac_send_data(d, data, npoints, rate)
- *
- * Send points to the DAC, including prepare or begin commands and changing
- * the point rate as necessary.
- */
-static int dac_send_data(struct etherdream *d, struct dac_point *data,
- int npoints, int rate) {
+*
+* Send points to the DAC, including prepare or begin commands and changing
+* the point rate as necessary.
+*/
+static int dac_send_data(struct etherdream* d, struct dac_point* data,
+ int npoints, int rate) {
int res;
- const struct dac_status *st = &d->conn.resp.dac_status;
+ const struct dac_status* st = &d->conn.resp.dac_status;
if (st->playback_state == 0) {
trace(d, "L: Sending prepare command...\n");
@@ -374,12 +392,15 @@ static int dac_send_data(struct etherdream *d, struct dac_point *data,
}
if (st->buffer_fullness > 1600 && st->playback_state == 1 \
- && !d->conn.dc_begin_sent) {
+ && !d->conn.dc_begin_sent) {
trace(d, "L: Sending begin command...\n");
- struct begin_command b = { .command = 'b', .point_rate = rate,
- .low_water_mark = 0 };
- if ((res = send_all(d, (const char *)&b, sizeof b)) < 0)
+ struct begin_command b = {
+ 'b',
+ 0,
+ (uint32_t)rate
+ };
+ if ((res = send_all(d, (const char*)&b, sizeof b)) < 0)
return res;
d->conn.dc_begin_sent = 1;
@@ -404,7 +425,7 @@ static int dac_send_data(struct etherdream *d, struct dac_point *data,
d->conn.dc_local_buffer.data[0].control |= DAC_CTRL_RATE_CHANGE;
/* Write the data */
- if ((res = send_all(d, (const char *)&d->conn.dc_local_buffer,
+ if ((res = send_all(d, (const char*)&d->conn.dc_local_buffer,
8 + npoints * sizeof(struct dac_point))) < 0)
return res;
@@ -421,29 +442,25 @@ static int dac_send_data(struct etherdream *d, struct dac_point *data,
|| d->conn.resp.dac_status.buffer_fullness < DEBUG_THRESHOLD_POINTS)
/* dac_loop(dv)
- *
- * Main thread function for sending data to the DAC.
- */
-static void *dac_loop(void *dv) {
- struct etherdream *d = (struct etherdream *)dv;
+*
+* Main thread function for sending data to the DAC.
+*/
+static void* dac_loop(etherdream * d) {
int res = 0;
- pthread_mutex_lock(&d->mutex);
-
while (1) {
/* Wait for us to have data */
int state;
while ((state = d->state) == ST_READY) {
-// trace(d, "L: waiting\n"); // MEMO
- pthread_cond_wait(&d->loop_cond, &d->mutex);
+ trace(d, "L: waiting\n");
+ std::unique_lock lock(d->mutex);
+ d->loop_cond.wait(lock);
}
- pthread_mutex_unlock(&d->mutex);
-
if (state != ST_RUNNING)
break;
- struct buffer_item *b = &d->buffer[d->frame_buffer_read];
+ struct buffer_item* b = &d->buffer[d->frame_buffer_read];
int cap;
int expected_used, expected_fullness;
@@ -451,9 +468,9 @@ static void *dac_loop(void *dv) {
res = 0;
/* Estimate how much data has been consumed since the
- * last time we got an ACK. */
+ * last time we got an ACK. */
long long time_diff = microseconds()
- - d->conn.dc_last_ack_time;
+ - d->conn.dc_last_ack_time;
expected_used = time_diff * b->pps / 1000000;
@@ -461,7 +478,7 @@ static void *dac_loop(void *dv) {
expected_used = 0;
expected_fullness =
- d->conn.resp.dac_status.buffer_fullness
+ d->conn.resp.dac_status.buffer_fullness
+ d->conn.unacked_points - expected_used;
/* Now, see how much data we should write. */
@@ -517,48 +534,56 @@ static void *dac_loop(void *dv) {
if (res < 0)
break;
- pthread_mutex_lock(&d->mutex);
+ {
+ std::unique_lock lock(d->mutex);
- /* What next? */
- b->idx += cap;
+ /* What next? */
+ b->idx += cap;
- if (b->idx < b->points) {
- /* There's more in this frame. */
- continue;
- }
+ if (b->idx < b->points) {
+ /* There's more in this frame. */
+ continue;
+ }
+
+ b->idx = 0;
- b->idx = 0;
-
- if (b->repeatcount > 1) {
- /* Play this frame again? */
- b->repeatcount--;
- } else if (d->frame_buffer_fullness > 1) {
- /* Move to the next frame */
- d->frame_buffer_fullness--;
- d->frame_buffer_read++;
- if (d->frame_buffer_read >= BUFFER_NFRAMES)
- d->frame_buffer_read = 0;
- pthread_cond_broadcast(&d->loop_cond);
- } else if (b->repeatcount >= 0) {
- /* Stop playing until we get a new frame. */
-// trace(d, "L: returning to idle\n"); // MEMO
- d->state = ST_READY;
- } else {
- /* repeatcount is negative and there's no new frame,
- * so just play this one over again. */
+ if (b->repeatcount > 1) {
+ /* Play this frame again? */
+ b->repeatcount--;
+ }
+ else if (d->frame_buffer_fullness > 1) {
+ /* Move to the next frame */
+ d->frame_buffer_fullness--;
+ d->frame_buffer_read++;
+ if (d->frame_buffer_read >= BUFFER_NFRAMES)
+ d->frame_buffer_read = 0;
+ d->loop_cond.notify_all();
+ }
+ else if (b->repeatcount >= 0) {
+ /* Stop playing until we get a new frame. */
+ trace(d, "L: returning to idle\n");
+ d->state = ST_READY;
+ }
+ else {
+ /* repeatcount is negative and there's no new frame,
+ * so just play this one over again. */
+ }
}
}
trace(d, "L: Shutting down.\n");
d->state = ST_SHUTDOWN;
+ d->loop_cond.notify_all();
return 0;
}
-int etherdream_connect(struct etherdream *d) {
+int etherdream_connect(struct etherdream* d) {
+ trace(d, "L: Connecting.\n");
+
// Initialize buffer
d->frame_buffer_read = 0;
d->frame_buffer_fullness = 0;
- memset(d->buffer, sizeof(d->buffer), 0);
+ memset(d->buffer, 0, sizeof(d->buffer));
// Connect to the DAC
if (dac_connect(d) < 0) {
@@ -568,42 +593,60 @@ int etherdream_connect(struct etherdream *d) {
d->state = ST_READY;
- int res = pthread_create(&d->workerthread, NULL, dac_loop, d);
- if (res) {
- trace(d, "!! Begin thread error: %s\n", strerror(res));
- return -1;
- }
+ d->workerthread = std::thread([d]() {
+ dac_loop(d);
+ });
trace(d, "Ready.\n");
return 0;
}
-void etherdream_disconnect(struct etherdream *d) {
- pthread_mutex_lock(&d->mutex);
+
+int etherdream_is_connected(struct etherdream* d) {
+ return d->state == ST_READY;
+}
+
+
+void etherdream_disconnect(struct etherdream* d) {
+ trace(d, "L: Disconnecting.\n");
+
+ d->mutex.lock();
if (d->state == ST_READY)
- pthread_cond_broadcast(&d->loop_cond);
+ d->loop_cond.notify_all();
d->state = ST_SHUTDOWN;
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
- pthread_join(d->workerthread, NULL);
+ d->workerthread.join();
+#ifdef _MSC_VER
+ closesocket(d->conn.dc_sock);
+#else
close(d->conn.dc_sock);
+#endif
}
/* etherdream_get_id(d)
- *
- * Documented in etherdream.h.
- */
-unsigned long etherdream_get_id(struct etherdream *d) {
+*
+* Documented in etherdream.h.
+*/
+unsigned long etherdream_get_id(struct etherdream* d) {
return d->dac_id;
}
+/* etherdream_get_in_addr(d)
+*
+* Documented in etherdream.h.
+*/
+const struct in_addr* etherdream_get_in_addr(struct etherdream* d) {
+ return &d->addr;
+}
+
/* etherdream_write(d, pts, npts, pps, reps)
- *
- * Documented in etherdream.h.
- */
-int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
- int npts, int pps, int reps) {
+*
+* Documented in etherdream.h.
+*/
+int etherdream_write(struct etherdream* d, const struct etherdream_point* pts,
+ int npts, int pps, int reps) {
/* Limit maximum frame size */
if (npts > BUFFER_POINTS_PER_FRAME)
@@ -613,19 +656,19 @@ int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
if (!reps)
return 0;
- pthread_mutex_lock(&d->mutex);
+ d->mutex.lock();
/* If not ready for a new frame, bail */
if (d->frame_buffer_fullness == BUFFER_NFRAMES) {
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
trace(d, "M: NOT READY: %d points, %d reps\n", npts, reps);
return -1;
}
- struct buffer_item *next = &d->buffer[(d->frame_buffer_read
- + d->frame_buffer_fullness) % BUFFER_NFRAMES];
+ struct buffer_item* next = &d->buffer[(d->frame_buffer_read
+ + d->frame_buffer_fullness) % BUFFER_NFRAMES];
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
// trace(d, "M: Writing: %d points, %d reps, %d pps\n", npts, reps, pps);
@@ -639,7 +682,7 @@ int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
next->data[i].g = pts[i].g;
next->data[i].b = pts[i].b;
next->data[i].i = pts[i].i;
- next->data[i].u1 = pts[i].u1;
+ next->data[i].u1 = pts[i].u1;
next->data[i].u2 = pts[i].u2;
next->data[i].control = 0;
}
@@ -649,59 +692,65 @@ int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
next->points = npts;
/* Advance buffer and signal the writing thread if necessary */
- pthread_mutex_lock(&d->mutex);
+ d->mutex.lock();
d->frame_buffer_fullness++;
if (d->state == ST_READY)
- pthread_cond_signal(&d->loop_cond);
+ d->loop_cond.notify_one();
d->state = ST_RUNNING;
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
return 0;
}
/* etherdream_is_ready(d)
- *
- * Documented in etherdream.h.
- */
-int etherdream_is_ready(struct etherdream *d) {
- pthread_mutex_lock(&d->mutex);
+*
+* Documented in etherdream.h.
+*/
+int etherdream_is_ready(struct etherdream* d) {
+ d->mutex.lock();
int ready = (d->frame_buffer_fullness != BUFFER_NFRAMES);
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
return ready;
}
/* etherdream_wait_for_ready(d)
- *
- * Documented in etherdream.h.
- */
-int etherdream_wait_for_ready(struct etherdream *d) {
- pthread_mutex_lock(&d->mutex);
- while (d->frame_buffer_fullness == BUFFER_NFRAMES)
- pthread_cond_wait(&d->loop_cond, &d->mutex);
- pthread_mutex_unlock(&d->mutex);
- return 0;
+*
+* Documented in etherdream.h.
+*/
+int etherdream_wait_for_ready(struct etherdream* d) {
+ d->mutex.lock();
+ while (d->frame_buffer_fullness == BUFFER_NFRAMES && d->state != ST_SHUTDOWN) {
+ std::unique_lock lock(d->mutex); d->loop_cond.wait(lock);
+ }
+ int is_shutdown = (d->state == ST_SHUTDOWN);
+ d->mutex.unlock();
+
+ if (is_shutdown) {
+ return -1;
+ }
+ else {
+ return 0;
+ }
}
/* etherdream_stop(d)
- *
- * Documented in etherdream.h.
- */
-int etherdream_stop(struct etherdream *d) {
- pthread_mutex_lock(&d->mutex);
+*
+* Documented in etherdream.h.
+*/
+int etherdream_stop(struct etherdream* d) {
+ d->mutex.lock();
if (d->state == ST_RUNNING)
d->buffer[d->frame_buffer_read].repeatcount = 0;
- pthread_mutex_unlock(&d->mutex);
+ d->mutex.unlock();
return 0;
}
/* watch_for_dacs(arg)
- *
- * Thread function for the broadcast monitor thread. This listens for UDP
- * broadcasts from Ether Dream boards on the network and adds them to our list.
- */
-static void *watch_for_dacs(void *arg) {
- (void)arg;
-
+*
+* Thread function for the broadcast monitor thread. This listens for UDP
+* broadcasts from Ether Dream boards on the network and adds them to our list.
+*/
+static void* watch_for_dacs() {
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
log_socket_error(NULL, "socket");
@@ -709,17 +758,18 @@ static void *watch_for_dacs(void *arg) {
}
int opt = 1;
- if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt,
- sizeof opt) < 0) {
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt,
+ sizeof opt) < 0) {
log_socket_error(NULL, "setsockopt SO_REUSEADDR");
return NULL;
}
- struct sockaddr_in addr = {
- .sin_family = AF_INET,
- .sin_addr.s_addr = htonl(INADDR_ANY), .sin_port = htons(7654)
- };
- if (bind(sock, (struct sockaddr *)&addr, sizeof addr) < 0) {
+ struct sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(7654);
+
+ if (bind(sock, (struct sockaddr*)&addr, sizeof addr) < 0) {
log_socket_error(NULL, "bind");
return NULL;
}
@@ -729,17 +779,21 @@ static void *watch_for_dacs(void *arg) {
while (1) {
struct sockaddr_in src;
struct dac_broadcast buf;
+#ifdef _MSC_VER
+ int srclen = sizeof src;
+#else
unsigned int srclen = sizeof src;
- int len = recvfrom(sock, (char *)&buf, sizeof buf, 0,
- (struct sockaddr *)&src, &srclen);
+#endif
+ int len = recvfrom(sock, (char*)&buf, sizeof buf, 0,
+ (struct sockaddr*)&src, &srclen);
if (len < 0) {
log_socket_error(NULL, "recvfrom");
return NULL;
}
/* See if this is a DAC we already knew about */
- pthread_mutex_lock(&dac_list_lock);
- struct etherdream *p = dac_list;
+ dac_list_lock.lock();
+ struct etherdream* p = dac_list;
while (p) {
if (p->addr.s_addr == src.sin_addr.s_addr)
break;
@@ -747,38 +801,30 @@ static void *watch_for_dacs(void *arg) {
}
if (p && (p->addr.s_addr == src.sin_addr.s_addr)) {
- pthread_mutex_unlock(&dac_list_lock);
+ dac_list_lock.unlock();
continue;
}
- pthread_mutex_unlock(&dac_list_lock);
+ dac_list_lock.unlock();
/* Make a new DAC entry */
- struct etherdream *new_dac;
- new_dac = (void *)malloc(sizeof (struct etherdream));
- if (!new_dac) {
- trace(NULL, "!! malloc(struct etherdream) failed\n");
- continue;
- }
-
- memset(new_dac, 0, sizeof *new_dac);
- pthread_cond_init(&new_dac->loop_cond, NULL);
- pthread_mutex_init(&new_dac->mutex, NULL);
+ struct etherdream* new_dac;
+ new_dac = new etherdream();
new_dac->addr = src.sin_addr;
memcpy(new_dac->mac_address, buf.mac_address, 6);
new_dac->dac_id = (buf.mac_address[3] << 16)
- | (buf.mac_address[4] << 8)
- | buf.mac_address[5];
+ | (buf.mac_address[4] << 8)
+ | buf.mac_address[5];
new_dac->sw_revision = buf.sw_revision;
new_dac->state = ST_DISCONNECTED;
trace(NULL, "_: Found new DAC: %s\n", inet_ntoa(src.sin_addr));
- pthread_mutex_lock(&dac_list_lock);
+ dac_list_lock.lock();
new_dac->next = dac_list;
dac_list = new_dac;
- pthread_mutex_unlock(&dac_list_lock);
+ dac_list_lock.unlock();
}
trace(NULL, "_: Exiting\n");
@@ -786,20 +832,10 @@ static void *watch_for_dacs(void *arg) {
}
/* etherdream_lib_start()
- *
- * Documented in etherdream.h.
- */
+*
+* Documented in etherdream.h.
+*/
int etherdream_lib_start(void) {
- // Get high-resolution timer info
-#if __MACH__
- timer_start = mach_absolute_time();
- mach_timebase_info_data_t timebase_info;
- mach_timebase_info(&timebase_info);
- timer_freq_numer = timebase_info.numer;
- timer_freq_denom = timebase_info.denom * 1000;
-#else
- clock_gettime(CLOCK_REALTIME, &start_time);
-#endif
// Set up the logging fd (just stderr for now)
trace_fp = stderr;
@@ -807,39 +843,50 @@ int etherdream_lib_start(void) {
fflush(trace_fp);
trace(NULL, "== libetherdream started ==\n");
- pthread_mutex_init(&dac_list_lock, NULL);
- pthread_t watcher_thread;
- pthread_create(&watcher_thread, NULL, watch_for_dacs, NULL);
+#ifdef _MSC_VER
+ {
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ wVersionRequested = MAKEWORD(2, 2);
+ auto err = WSAStartup(wVersionRequested, &wsaData);
+ if (err != 0) {
+ printf("WSAStartup failed with error: %d\n", err);
+ return err;
+ }
+ }
+#endif
+
+ watcherThread = std::thread(watch_for_dacs);
return 0;
}
/* etherdream_dac_count()
- *
- * Documented in etherdream.h.
- */
+*
+* Documented in etherdream.h.
+*/
int etherdream_dac_count(void) {
- pthread_mutex_lock(&dac_list_lock);
+ dac_list_lock.lock();
int count = 0;
- struct etherdream *d = dac_list;
+ struct etherdream* d = dac_list;
while (d) {
d = d->next;
count++;
}
- pthread_mutex_unlock(&dac_list_lock);
+ dac_list_lock.unlock();
trace(NULL, "== etherdream_lib_get_dac_count(): %d\n", count);
return count;
}
/* etherdream_get()
- *
- * Documented in etherdream.h.
- */
-struct etherdream *etherdream_get(unsigned long idx) {
- struct etherdream *d = dac_list;
+*
+* Documented in etherdream.h.
+*/
+struct etherdream* etherdream_get(unsigned long idx) {
+ struct etherdream* d = dac_list;
unsigned long i = 0;
while (d) {
@@ -851,4 +898,4 @@ struct etherdream *etherdream_get(unsigned long idx) {
}
return NULL;
-}
+}
\ No newline at end of file
diff --git a/libs/driver/libetherdream/etherdream.h b/libs/driver/libetherdream/etherdream.h
index 5c7f5e4..29e531a 100755
--- a/libs/driver/libetherdream/etherdream.h
+++ b/libs/driver/libetherdream/etherdream.h
@@ -1,69 +1,71 @@
#ifndef ETHERDREAM_H
#define ETHERDREAM_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include
-#include
-
#define _POSIX_C_SOURCE 199309L
#define _DARWIN_C_SOURCE 1
-
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_WARNINGS
+#define _WINSOCK_DEPRECATED_NO_WARNINGS
+#include
+#else
#include
-#include
#include
#include
-#include
-#include
-#include
-#include
-#include
#include
#include
-#include
+#endif
+
+#include
+#include
+
+#include
#include
-#include
-
-#ifdef __MACH__
-#include
-#include
+#include
+
+#include "../common/protocol.h"
+
+#ifdef __cplusplus
+extern "C"
+{
#endif
-struct etherdream_point {
- int16_t x;
- int16_t y;
- uint16_t r;
- uint16_t g;
- uint16_t b;
- uint16_t i;
- uint16_t u1;
- uint16_t u2;
-};
-
-
+#include
+
#define BUFFER_POINTS_PER_FRAME 16000
-#define BUFFER_NFRAMES 2
-#define MAX_LATE_ACKS 64
-#define MIN_SEND_POINTS 40
-#define DEFAULT_TIMEOUT 2000000
-#define DEBUG_THRESHOLD_POINTS 800
-
-
- struct etherdream_conn {
+#define BUFFER_NFRAMES 2
+#define MAX_LATE_ACKS 64
+#define MIN_SEND_POINTS 40
+#define DEFAULT_TIMEOUT 2000000
+#define DEBUG_THRESHOLD_POINTS 800
+
+ struct etherdream_point
+ {
+ int16_t x;
+ int16_t y;
+ uint16_t r;
+ uint16_t g;
+ uint16_t b;
+ uint16_t i;
+ uint16_t u1;
+ uint16_t u2;
+ };
+
+ struct etherdream_conn
+ {
int dc_sock;
char dc_read_buf[1024];
int dc_read_buf_size;
- struct dac_response resp;
+ dac_response resp;
long long dc_last_ack_time;
-
- struct {
+
+ struct
+ {
struct queue_command queue;
struct data_command_header header;
struct dac_point data[1000];
} __attribute__((packed)) dc_local_buffer;
-
+
int dc_begin_sent;
int ackbuf[MAX_LATE_ACKS];
int ackbuf_prod;
@@ -71,131 +73,145 @@ struct etherdream_point {
int unacked_points;
int pending_meta_acks;
};
-
- struct buffer_item {
+
+ struct buffer_item
+ {
struct dac_point data[BUFFER_POINTS_PER_FRAME];
int points;
int pps;
int repeatcount;
int idx;
};
-
- enum dac_state {
+
+ enum dac_state
+ {
ST_DISCONNECTED,
ST_READY,
ST_RUNNING,
ST_BROKEN,
ST_SHUTDOWN
};
-
- struct etherdream {
- pthread_mutex_t mutex;
- pthread_cond_t loop_cond;
-
+
+ struct etherdream
+ {
+ std::mutex mutex;
+ std::condition_variable loop_cond;
+
struct buffer_item buffer[BUFFER_NFRAMES];
int frame_buffer_read;
int frame_buffer_fullness;
int bounce_count;
-
- pthread_t workerthread;
-
+
+ std::thread workerthread;
+
struct in_addr addr;
struct etherdream_conn conn;
unsigned long dac_id;
int sw_revision;
char mac_address[6];
char version[32];
-
+
enum dac_state state;
-
- struct etherdream * next;
+
+ etherdream *next;
};
-
-struct etherdream;
-
-/* etherdream_lib_start()
- *
- * Initialize the Ether Dream library and start a background thread to listen
- * for DAC broadcasts. This should be called exactly once at program startup.
- *
- * Returns 0 on success, -1 on failure.
- */
-int etherdream_lib_start(void);
-
-/* etherdream_dac_count()
- *
- * Return the number of detected DACs since etherdream_lib_start() was called.
- * Ether Dream DACs broadcast once per second, so calling code should wait a
- * little over a second after etherdream_lib_start() to ensure that all DACs
- * on the network are seen.
- */
-int etherdream_dac_count(void);
-
-/* etherdream_get(idx)
- *
- * Return the i'th detected DAC. This function accepts either an integer index
- * (0-based) or an ID value as returned by etherdream_get_id(). Returns NULL
- * if the requested DAC is not available.
- */
-struct etherdream *etherdream_get(unsigned long idx);
-
-/* etherdream_get_id(d)
- *
- * Return the ID value (equal to the second half of the MAC address, when
- * represented in hex) of the given Ether Dream. Does not require that a
- * connection to d has been established.
- */
-unsigned long etherdream_get_id(struct etherdream *d);
-
-/* etherdream_connect(d)
- *
- * Open a connection to d. This must be called before most other etherdream_
- * functions can be used.
- */
-int etherdream_connect(struct etherdream *d);
-
-/* etherdream_is_ready(d)
- *
- * Return 1 if the local buffer for d can accept more frames, 0 if not, -1 on
- * error (if the connection to d has not been opened or has failed).
- */
-int etherdream_is_ready(struct etherdream *d);
-
-/* etherdream_wait_for_ready(d)
- *
- * Block the invoking thread until more data can be written to d. Returns 0 on
- * success, -1 if the connection to d is not open or has failed.
- */
-int etherdream_wait_for_ready(struct etherdream *d);
-
-/* etherdream_write(d, pts, npts, pps, repeatcount)
- *
- * Write a "frame" consisting of pts (length npts) to d.
- *
- * If repeatcount is -1, pts will be sent to the laser repeatedly until new
- * data is received or until etherdream_stop is called. Otherwise, the points
- * will be sent repeatedly at most npts times, and then the stream will
- * automatically stop. pps specifies the output rate (30000 is a common value).
- * repeatcount must not be 0.
- *
- * The Ether Dream uses a continuous streaming protocol, so if new frames are
- * continuously sent, frame boundaries are not visible; however, to reduce
- * overhead, frames should be reasonably large (at least 50-100 points).
- */
-int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
- int npts, int pps, int repeatcount);
-
-/* etherdream_stop(d)
- *
- * Stop output from d as soon as the current frame is finished.
- */
-int etherdream_stop(struct etherdream *d);
-
-/* etherdream_disconnect(d)
- *
- * Close the TCP connection to d.
- */
-void etherdream_disconnect(struct etherdream *d);
+
+ /* etherdream_lib_start()
+ *
+ * Initialize the Ether Dream library and start a background thread to listen
+ * for DAC broadcasts. This should be called exactly once at program startup.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+ int etherdream_lib_start(void);
+
+ /* etherdream_dac_count()
+ *
+ * Return the number of detected DACs since etherdream_lib_start() was called.
+ * Ether Dream DACs broadcast once per second, so calling code should wait a
+ * little over a second after etherdream_lib_start() to ensure that all DACs
+ * on the network are seen.
+ */
+ int etherdream_dac_count(void);
+
+ /* etherdream_get(idx)
+ *
+ * Return the [i]'th detected DAC. This function accepts either an integer index
+ * (0-based) or an ID value as returned by etherdream_get_id(). Returns NULL
+ * if the requested DAC is not available.
+ */
+ struct etherdream *etherdream_get(unsigned long idx);
+
+ /* etherdream_get_id(d)
+ *
+ * Return the ID value (equal to the second half of the MAC address, when
+ * represented in hex) of the given Ether Dream. Does not require that a
+ * connection to d has been established.
+ */
+ unsigned long etherdream_get_id(struct etherdream *d);
+
+ /* etherdream_get_in_addr(d)
+ *
+ * Return the IP address of the given Ether Dream. Does not require that
+ * a connection to d has been established.
+ */
+ const struct in_addr *etherdream_get_in_addr(struct etherdream *d);
+
+ /* etherdream_connect(d)
+ *
+ * Open a connection to d. This must be called before most other etherdream_
+ * functions can be used.
+ */
+ int etherdream_connect(struct etherdream *d);
+
+ /* etherdream_is_connected(d)
+ *
+ * Returns 1 if the network connection to d is connected, 0 if not.
+ */
+ int etherdream_is_connected(struct etherdream *d);
+
+ /* etherdream_is_ready(d)
+ *
+ * Return 1 if the local buffer for d can accept more frames, 0 if not, -1 on
+ * error (if the connection to d has not been opened or has failed).
+ */
+ int etherdream_is_ready(struct etherdream *d);
+
+ /* etherdream_wait_for_ready(d)
+ *
+ * Block the invoking thread until more data can be written to d. Returns 0 on
+ * success, -1 if the connection to d is not open or has failed.
+ */
+ int etherdream_wait_for_ready(struct etherdream *d);
+
+ /* etherdream_write(d, pts, npts, pps, repeatcount)
+ *
+ * Write a "frame" consisting of pts (length npts) to d.
+ *
+ * If repeatcount is -1, pts will be sent to the laser repeatedly until new
+ * data is received or until etherdream_stop is called. Otherwise, the points
+ * will be sent repeatedly at most npts times, and then the stream will
+ * automatically stop. pps specifies the output rate (30000 is a common value).
+ * repeatcount must not be 0.
+ *
+ * The Ether Dream uses a continuous streaming protocol, so if new frames are
+ * continuously sent, frame boundaries are not visible; however, to reduce
+ * overhead, frames should be reasonably large (at least 50-100 points).
+ */
+ int etherdream_write(struct etherdream *d, const struct etherdream_point *pts,
+ int npts, int pps, int repeatcount);
+
+ /* etherdream_stop(d)
+ *
+ * Stop output from d as soon as the current frame is finished.
+ */
+ int etherdream_stop(struct etherdream *d);
+
+ /* etherdream_disconnect(d)
+ *
+ * Close the TCP connection to d.
+ */
+ void etherdream_disconnect(struct etherdream *d);
#ifdef __cplusplus
} // extern "c"
diff --git a/libs/driver/libetherdream/test.c b/libs/driver/libetherdream/test.c
index 5ffec41..60a8e18 100755
--- a/libs/driver/libetherdream/test.c
+++ b/libs/driver/libetherdream/test.c
@@ -2,7 +2,8 @@
#include
#include
-#include
+//#include
+#include
#include "etherdream.h"
@@ -21,25 +22,84 @@ uint16_t colorsin(float pos) {
return res;
}
-void fill_circle(float phase) {
+void fill_circle(float phase, int mode) {
int i;
for (i = 0; i < CIRCLE_POINTS; i++) {
- struct etherdream_point *pt = &circle[i];
+ struct etherdream_point* pt = &circle[i];
float ip = (float)i * 2.0 * M_PI / (float)CIRCLE_POINTS;
- pt->x = sin(ip) * 20000;
- pt->y = cos(ip) * 20000;
- pt->r = colorsin(ip + phase);
- pt->g = colorsin(ip + (2.0 * M_PI / 3.0) + phase);
- pt->b = colorsin(ip + (4.0 * M_PI / 3.0) + phase);
+ float ipf = fmod(ip + phase, 2.0 * M_PI);;
+
+ switch (mode) {
+ default:
+ case 0: {
+ float cmult = .05 * sin(30 * (ip - phase / 3));
+ pt->x = sin(ip) * 20000 * (1 + cmult);
+ pt->y = cos(ip) * 20000 * (1 + cmult);
+ break;
+ }
+ case 1: {
+ float cmult = .10 * sin(10 * (ip - phase / 3));
+ pt->x = sin(ip) * 20000 * (1 + cmult);
+ pt->y = cos(ip) * 20000 * (1 + cmult);
+ break;
+ /* XXX broken */
+/*
+ float R = 3;
+ float r = 5;
+ pt->x = 2000 * ((R-r)*cos(ip+phase) + r*cos((R-r)*ip/r));
+ pt->y = 2000 * ((R-r)*sin(ip+phase) - r*sin((R-r)*ip/r));
+ break;
+*/
+ }
+ case 2: {
+ ip *= 3;
+ float R = 5;
+ float r = 3;
+ float D = 5;
+
+ pt->x = 2500 * ((R - r) * cos(ip + phase) + D * cos((R - r) * ip / r));
+ pt->y = 2500 * ((R - r) * sin(ip + phase) - D * sin((R - r) * ip / r));
+ break;
+ }
+ case 3: {
+ int n = 5;
+ float R = 5 * cos(M_PI / n) / cos(fmod(ip, (2 * M_PI / n)) - (M_PI / n));
+ pt->x = 3500 * R * cos(ip + phase);
+ pt->y = 3500 * R * sin(ip + phase);
+ break;
+ }
+ case 4: {
+ float Xo = sin(ip);
+ pt->x = 20000 * Xo * cos(phase / 4);
+ pt->y = 20000 * Xo * -sin(phase / 4);
+ ipf = fmod(((Xo + 1) / 2.0) + phase / 3, 1.0) * 2 * M_PI;
+ }
+ }
+
+ pt->r = colorsin(ipf);
+ pt->g = colorsin(ipf + (2.0 * M_PI / 3.0));
+ pt->b = colorsin(ipf + (4.0 * M_PI / 3.0));
+ /*
+ if (ipf < 2.0 * M_PI / 3.0) {
+ pt->r = 65535;
+ pt->g = pt->b = 0;
+ } else if (ipf < 4.0 * M_PI / 3.0) {
+ pt->g = 65535;
+ pt->r = pt->b = 0;
+ } else {
+ pt->b = 65535;
+ pt->r = pt->g = 0;
+ }
+ */
}
}
-int _main() {
+int main(int argc, char** argv) {
etherdream_lib_start();
/* Sleep for a bit over a second, to ensure that we see broadcasts
* from all available DACs. */
- usleep(1200000);
+ //usleep(1200000);
int cc = etherdream_dac_count();
if (!cc) {
@@ -47,13 +107,19 @@ int _main() {
return 0;
}
+ int mode;
+ if (argc > 1)
+ mode = atoi(argv[1]);
+ else
+ mode = 0;
+
int i;
for (i = 0; i < cc; i++) {
printf("%d: Ether Dream %06lx\n", i,
etherdream_get_id(etherdream_get(i)));
}
- struct etherdream *d = etherdream_get(0);
+ struct etherdream* d = etherdream_get(0);
printf("Connecting...\n");
if (etherdream_connect(d) < 0)
@@ -61,7 +127,7 @@ int _main() {
i = 0;
while (1) {
- fill_circle((float)i / 50);
+ fill_circle((float)i / 50, mode);
int res = etherdream_write(d, circle, CIRCLE_POINTS, 30000, 1);
if (res != 0) {
printf("write %d\n", res);
diff --git a/src/ofxEtherdream.cpp b/src/ofxEtherdream.cpp
index b8de96b..3cea9f8 100755
--- a/src/ofxEtherdream.cpp
+++ b/src/ofxEtherdream.cpp
@@ -1,173 +1,208 @@
#include "ofxEtherdream.h"
//--------------------------------------------------------------
-void ofxEtherdream::setup(bool bStartThread, int idEtherdream) {
+void ofxEtherdream::setup(bool bStartThread, int idEtherdream)
+{
idEtherdreamConnection = idEtherdream;
-
+
etherdream_lib_start();
-
+
setPPS(30000);
setWaitBeforeSend(false);
-
- /* Sleep for a bit over a second, to ensure that we see broadcasts
- * from all available DACs. */
- usleep(1000000);
-
+
+/* Sleep for a bit over a second, to ensure that we see broadcasts
+ * from all available DACs. */
+#ifdef _MSC_VER
+ Sleep(1000);
+#else
+ usleep(1000000);
+#endif
+
init();
-
- if(bStartThread) start();
-}
+ if (bStartThread)
+ start();
+}
//--------------------------------------------------------------
-bool ofxEtherdream::stateIsFound() {
+bool ofxEtherdream::stateIsFound()
+{
return state == ETHERDREAM_FOUND;
}
//--------------------------------------------------------------
-bool ofxEtherdream::checkConnection(bool bForceReconnect) {
- if(device->state == ST_SHUTDOWN || device->state == ST_BROKEN || device->state == ST_DISCONNECTED) {
-
- if(bForceReconnect) {
+bool ofxEtherdream::checkConnection(bool bForceReconnect)
+{
+ if (device->state == ST_SHUTDOWN || device->state == ST_BROKEN || device->state == ST_DISCONNECTED)
+ {
+
+ if (bForceReconnect)
+ {
kill();
setup(true, idEtherdreamConnection);
}
-
+
return false;
}
return true;
}
//--------------------------------------------------------------
-void ofxEtherdream::init() {
+void ofxEtherdream::init()
+{
int device_num = etherdream_dac_count();
- if (!device_num || idEtherdreamConnection>device_num) {
- ofLogWarning() << "ofxEtherdream::init - No DACs found";
- return;
- }
-
- for (int i=0; i device_num)
+ {
+ ofLogWarning() << "ofxEtherdream::init - No DACs found";
+ return;
}
-
+
+ for (int i = 0; i < device_num; i++)
+ {
+ ofLogNotice() << "ofxEtherdream::init - " << i << " Ether Dream " << etherdream_get_id(etherdream_get(i));
+ }
+
device = etherdream_get(idEtherdreamConnection);
-
+
ofLogNotice() << "ofxEtherdream::init - Connecting...";
- if (etherdream_connect(device) < 0) return;
+ if (etherdream_connect(device) < 0)
+ return;
ofLogNotice() << "ofxEtherdream::init - done";
-
+
state = ETHERDREAM_FOUND;
}
//--------------------------------------------------------------
-void ofxEtherdream::threadedFunction() {
- while (isThreadRunning() != 0) {
-
- switch (state) {
- case ETHERDREAM_NOTFOUND:
- if(bAutoConnect) init();
- break;
-
- case ETHERDREAM_FOUND:
- if(lock()) {
- send();
- unlock();
- }
- break;
+void ofxEtherdream::threadedFunction()
+{
+ while (isThreadRunning() != 0)
+ {
+
+ switch (state)
+ {
+ case ETHERDREAM_NOTFOUND:
+ if (bAutoConnect)
+ init();
+ break;
+
+ case ETHERDREAM_FOUND:
+ if (lock())
+ {
+ send();
+ unlock();
+ }
+ break;
}
}
}
//--------------------------------------------------------------
-void ofxEtherdream::start() {
- startThread(); // TODO: blocking or nonblocking?
+void ofxEtherdream::start()
+{
+ startThread(); // TODO: blocking or nonblocking?
}
//--------------------------------------------------------------
-void ofxEtherdream::stop() {
+void ofxEtherdream::stop()
+{
stopThread();
}
//--------------------------------------------------------------
-void ofxEtherdream::send() {
- if(!stateIsFound() || points.empty()) return;
-
- if(bWaitBeforeSend) etherdream_wait_for_ready(device);
- else if(!etherdream_is_ready(device)) return;
-
+void ofxEtherdream::send()
+{
+ if (!stateIsFound() || points.empty())
+ return;
+
+ if (bWaitBeforeSend)
+ etherdream_wait_for_ready(device);
+ else if (!etherdream_is_ready(device))
+ return;
+
// DODGY HACK: casting ofxIlda::Point* to etherdream_point*
- int res = etherdream_write(device, (etherdream_point*)points.data(), points.size(), pps, 1);
- if (res != 0) {
+ int res = etherdream_write(device, (etherdream_point *)points.data(), points.size(), pps, 1);
+ if (res != 0)
+ {
ofLogVerbose() << "ofxEtherdream::write " << res;
}
points.clear();
}
-
//--------------------------------------------------------------
-void ofxEtherdream::clear() {
- if(lock()) {
+void ofxEtherdream::clear()
+{
+ if (lock())
+ {
points.clear();
unlock();
}
}
//--------------------------------------------------------------
-void ofxEtherdream::addPoints(const vector& _points) {
- if(lock()) {
- if(!_points.empty()) {
+void ofxEtherdream::addPoints(const vector &_points)
+{
+ if (lock())
+ {
+ if (!_points.empty())
+ {
points.insert(points.end(), _points.begin(), _points.end());
}
unlock();
}
}
-
//--------------------------------------------------------------
-void ofxEtherdream::addPoints(const ofxIlda::Frame &ildaFrame) {
+void ofxEtherdream::addPoints(const ofxIlda::Frame &ildaFrame)
+{
addPoints(ildaFrame.getPoints());
}
-
//--------------------------------------------------------------
-void ofxEtherdream::setPoints(const vector& _points) {
- if(lock()) {
+void ofxEtherdream::setPoints(const vector &_points)
+{
+ if (lock())
+ {
points = _points;
unlock();
}
}
-
//--------------------------------------------------------------
-void ofxEtherdream::setPoints(const ofxIlda::Frame &ildaFrame) {
+void ofxEtherdream::setPoints(const ofxIlda::Frame &ildaFrame)
+{
setPoints(ildaFrame.getPoints());
}
//--------------------------------------------------------------
-void ofxEtherdream::setWaitBeforeSend(bool b) {
- if(lock()) {
+void ofxEtherdream::setWaitBeforeSend(bool b)
+{
+ if (lock())
+ {
bWaitBeforeSend = b;
unlock();
}
}
//--------------------------------------------------------------
-bool ofxEtherdream::getWaitBeforeSend() const {
+bool ofxEtherdream::getWaitBeforeSend() const
+{
return bWaitBeforeSend;
}
-
//--------------------------------------------------------------
-void ofxEtherdream::setPPS(int i) {
- if(lock()) {
+void ofxEtherdream::setPPS(int i)
+{
+ if (lock())
+ {
pps = i;
unlock();
}
}
//--------------------------------------------------------------
-int ofxEtherdream::getPPS() const {
+int ofxEtherdream::getPPS() const
+{
return pps;
}