2
* Pure Data Packet module. packet forth console
3
* Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 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 General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
#include <sys/types.h>
32
#include "pdp_debug.h"
36
#include "pdp_packet.h"
45
/* raw input from a unix pipe */
47
typedef struct rawin_struct
52
t_outlet *x_sync_outlet;
56
t_pdp_list *x_queue; // packet queue
59
pthread_mutex_t x_mut;
60
pthread_attr_t x_attr;
64
int x_giveup; // 1-> terminate reader thread
65
int x_active; // 1-> reader thread is launched
66
int x_done; // 1-> reader thread has exited
75
static inline void lock(t_rawin *x){pthread_mutex_lock(&x->x_mut);}
76
static inline void unlock(t_rawin *x){pthread_mutex_unlock(&x->x_mut);}
78
static void rawin_close(t_rawin *x);
79
static void tick(t_rawin *x)
81
/* send all packets in queue to outlet */
83
while (x->x_queue->elements){
84
outlet_pdp_atom(x->x_outlet, x->x_queue->first);
85
pdp_list_pop(x->x_queue); // pop stale reference
88
clock_delay(x->x_clock, PERIOD);
90
/* check if thread is done */
91
if (x->x_done) rawin_close(x);
95
static void move_current_to_queue(t_rawin *x, int packet)
98
pdp_list_add_back(x->x_queue, a_packet, (t_pdp_word)packet);
102
static void *rawin_thread(void *y)
106
t_rawin *x = (t_rawin *)y;
111
//D pdp_post("pipe: %s", x->x_pipe->s_name);
112
//D pdp_post("type: %s", x->x_type->s_name);
115
if (-1 == (pipe = open(x->x_pipe->s_name, O_RDONLY|O_NONBLOCK))){
116
perror(x->x_pipe->s_name);
120
/* main loop (packets) */
127
pdp_post("WARNING: deleting stale packet");
128
pdp_packet_mark_unused(packet);
130
packet = pdp_factory_newpacket(x->x_type);
132
pdp_post("ERROR: can't create packet. type = %s", x->x_type->s_name);
137
data = pdp_packet_data(packet);
138
left = pdp_packet_data_size(packet);
139
// D pdp_post("packet %d, data %x, size %d", packet, data, left);
141
/* inner loop: pipe reads */
145
struct timeval tv = {0,10000};
147
/* check if we need to stop */
149
pdp_packet_mark_unused(packet);
152
/* select, with timeout */
154
FD_SET(pipe, &inset);
155
if (-1 == select(pipe+1, &inset, NULL,NULL, &tv)){
156
pdp_post("select error");
160
/* if ready, read, else retry */
161
if (FD_ISSET(pipe, &inset)){
162
int bytes = read(pipe, data, left);
164
/* if no bytes are read, pipe is closed */
173
move_current_to_queue(x, packet);
192
static void rawin_type(t_rawin *x, t_symbol *type)
194
x->x_type = pdp_gensym(type->s_name);
197
static void rawin_open(t_rawin *x, t_symbol *pipe)
199
/* save pipe name if not empty */
200
if (pipe->s_name[0]) {x->x_pipe = pipe;}
203
pdp_post("already open");
209
pthread_create(&x->x_thread, &x->x_attr, rawin_thread , x);
213
static void rawin_close(t_rawin *x)
216
if (!x->x_active) return;
218
/* stop thread: set giveup + wait */
220
pthread_join(x->x_thread, NULL);
224
outlet_bang(x->x_sync_outlet);
225
pdp_post("connection to %s closed", x->x_pipe->s_name);
233
static void rawin_free(t_rawin *x)
236
clock_free(x->x_clock);
237
pdp_tree_strip_packets(x->x_queue);
238
pdp_tree_free(x->x_queue);
241
t_class *rawin_class;
244
static void *rawin_new(t_symbol *pipe, t_symbol *type)
248
pdp_post("%s %s", pipe->s_name, type->s_name);
250
/* allocate & init */
251
x = (t_rawin *)pd_new(rawin_class);
252
x->x_outlet = outlet_new(&x->x_obj, &s_anything);
253
x->x_sync_outlet = outlet_new(&x->x_obj, &s_anything);
254
x->x_clock = clock_new(x, (t_method)tick);
255
x->x_queue = pdp_list_new(0);
259
x->x_type = pdp_gensym("image/YCrCb/320x240"); //default
260
x->x_pipe = gensym("/tmp/pdpraw"); // default
261
pthread_attr_init(&x->x_attr);
262
pthread_mutex_init(&x->x_mut, NULL);
263
clock_delay(x->x_clock, PERIOD);
267
if (pipe->s_name[0]) x->x_pipe = pipe;
281
void pdp_rawin_setup(void)
285
/* create a standard pd class: [pdp_rawin pipe type] */
286
rawin_class = class_new(gensym("pdp_rawin"), (t_newmethod)rawin_new,
287
(t_method)rawin_free, sizeof(t_rawin), 0, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
289
/* add global message handler */
290
class_addmethod(rawin_class, (t_method)rawin_type, gensym("type"), A_SYMBOL, A_NULL);
291
class_addmethod(rawin_class, (t_method)rawin_open, gensym("open"), A_DEFSYMBOL, A_NULL);
292
class_addmethod(rawin_class, (t_method)rawin_close, gensym("close"), A_NULL);