version 1.19, 2009/07/25 08:44:27 |
version 1.20, 2009/07/25 10:52:19 |
|
|
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include "aproc.h" |
|
#include "abuf.h" |
#include "abuf.h" |
#include "sock.h" |
#include "aproc.h" |
#include "dev.h" |
|
#include "conf.h" |
#include "conf.h" |
|
#include "dev.h" |
#include "midi.h" |
#include "midi.h" |
#include "opt.h" |
#include "opt.h" |
|
#include "sock.h" |
|
|
int sock_attach(struct sock *, int); |
int sock_attach(struct sock *, int); |
int sock_read(struct sock *); |
int sock_read(struct sock *); |
|
|
DPRINTFN(4, "rsock_out: %p\n", f); |
DPRINTFN(4, "rsock_out: %p\n", f); |
|
|
/* |
/* |
* when calling sock_read(), we may receive a ``STOP'' command, |
* When calling sock_read(), we may receive a ``STOP'' command, |
* and detach ``obuf''. In this case, there's no more caller and |
* and detach ``obuf''. In this case, there's no more caller and |
* we'll stop processing further messages, resulting in a dead lock. |
* we'll stop processing further messages, resulting in a deadlock. |
* The solution is to iterate over sock_read() in order to |
* The solution is to iterate over sock_read() in order to |
* consume all messages(). |
* consume all messages(). |
*/ |
*/ |
|
|
|
|
DPRINTFN(4, "wsock_in: %p\n", f); |
DPRINTFN(4, "wsock_in: %p\n", f); |
/* |
/* |
* see remark in rsock_out() |
* See remark in rsock_out(). |
*/ |
*/ |
for (;;) { |
for (;;) { |
if (!sock_write(f)) |
if (!sock_write(f)) |
|
|
}; |
}; |
|
|
/* |
/* |
* initialise socket in the SOCK_HELLO state with default |
* Initialise socket in the SOCK_HELLO state with default |
* parameters |
* parameters. |
*/ |
*/ |
struct sock * |
struct sock * |
sock_new(struct fileops *ops, int fd) |
sock_new(struct fileops *ops, int fd) |
|
|
} |
} |
|
|
/* |
/* |
* free buffers |
* Free buffers. |
*/ |
*/ |
void |
void |
sock_freebuf(struct sock *f) |
sock_freebuf(struct sock *f) |
|
|
} |
} |
|
|
/* |
/* |
* allocate buffers, so client can start filling write-end. |
* Allocate buffers, so client can start filling write-end. |
*/ |
*/ |
void |
void |
sock_allocbuf(struct sock *f) |
sock_allocbuf(struct sock *f) |
|
|
} |
} |
|
|
/* |
/* |
* free buffers |
* Set volume. |
*/ |
*/ |
void |
void |
sock_setvol(struct sock *f, int vol) |
sock_setvol(struct sock *f, int vol) |
|
|
} |
} |
|
|
/* |
/* |
* attach play and/or record buffers to dev_mix and/or dev_sub |
* Attach play and/or record buffers to dev_mix and/or dev_sub. |
*/ |
*/ |
int |
int |
sock_attach(struct sock *f, int force) |
sock_attach(struct sock *f, int force) |
|
|
wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist); |
wbuf = LIST_FIRST(&f->pipe.file.wproc->ibuflist); |
|
|
/* |
/* |
* if in SOCK_START state, dont attach until |
* If in SOCK_START state, dont attach until |
* the buffer isn't completely filled |
* the buffer isn't completely filled. |
*/ |
*/ |
if (!force && rbuf && ABUF_WOK(rbuf)) |
if (!force && rbuf && ABUF_WOK(rbuf)) |
return 0; |
return 0; |
|
|
f->pstate = SOCK_RUN; |
f->pstate = SOCK_RUN; |
|
|
/* |
/* |
* attach them to the device |
* Attach them to the device. |
*/ |
*/ |
dev_attach(f->pipe.file.name, |
dev_attach(f->pipe.file.name, |
(f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun, |
(f->mode & AMSG_PLAY) ? rbuf : NULL, &f->rpar, f->xrun, |
|
|
dev_setvol(rbuf, f->vol); |
dev_setvol(rbuf, f->vol); |
|
|
/* |
/* |
* send the initial position, if needed |
* Send the initial position, if needed. |
*/ |
*/ |
for (;;) { |
for (;;) { |
if (!sock_write(f)) |
if (!sock_write(f)) |
|
|
} |
} |
|
|
/* |
/* |
* read a message from the file descriptor, return 1 if done, 0 |
* Read a message from the file descriptor, return 1 if done, 0 |
* otherwise. The message is stored in f->rmsg |
* otherwise. The message is stored in f->rmsg. |
*/ |
*/ |
int |
int |
sock_rmsg(struct sock *f) |
sock_rmsg(struct sock *f) |
|
|
} |
} |
|
|
/* |
/* |
* write a message to the file descriptor, return 1 if done, 0 |
* Write a message to the file descriptor, return 1 if done, 0 |
* otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo" |
* otherwise. The "m" argument is f->rmsg or f->wmsg, and the "ptodo" |
* points to the f->rtodo or f->wtodo respectively. |
* points to the f->rtodo or f->wtodo respectively. |
*/ |
*/ |
|
|
} |
} |
|
|
/* |
/* |
* read data chunk from the file descriptor, return 1 if at least one |
* Read data chunk from the file descriptor, return 1 if at least one |
* byte was read, 0 if the file blocked. |
* byte was read, 0 if the file blocked. |
*/ |
*/ |
int |
int |
|
|
} |
} |
|
|
/* |
/* |
* write data chunk to the file descriptor, return 1 if at least one |
* Write data chunk to the file descriptor, return 1 if at least one |
* byte was written, 0 if the file blocked. |
* byte was written, 0 if the file blocked. |
*/ |
*/ |
int |
int |
|
|
if (f->pstate == SOCK_MIDI) |
if (f->pstate == SOCK_MIDI) |
return 0; |
return 0; |
/* |
/* |
* there's no dev_detach() routine yet, |
* There's no dev_detach() routine yet, |
* so now we abruptly destroy the buffer. |
* so now we abruptly destroy the buffer. |
* Until we implement dev_detach, complete |
* Until we implement dev_detach, complete |
* the packet with zeros... |
* the packet with zeros... |
|
|
} |
} |
|
|
/* |
/* |
* execute message in f->rmsg and change the state accordingly; return 1 |
* Execute message in f->rmsg and change the state accordingly; return 1 |
* on success, and 0 on failure, in which case the socket is destroyed. |
* on success, and 0 on failure, in which case the socket is destroyed. |
*/ |
*/ |
int |
int |
|
|
} |
} |
|
|
/* |
/* |
* create a new data/pos message |
* Create a new data/pos message. |
*/ |
*/ |
int |
int |
sock_buildmsg(struct sock *f) |
sock_buildmsg(struct sock *f) |
|
|
} |
} |
|
|
/* |
/* |
* if pos changed, build a MOVE message |
* If pos changed, build a MOVE message. |
*/ |
*/ |
if (f->tickpending && f->delta >= 0) { |
if (f->tickpending && f->delta >= 0) { |
DPRINTFN(4, "sock_buildmsg: %p: POS: %d\n", f, f->delta); |
DPRINTFN(4, "sock_buildmsg: %p: POS: %d\n", f, f->delta); |
|
|
} |
} |
|
|
/* |
/* |
* if data available, build a DATA message |
* If data available, build a DATA message. |
*/ |
*/ |
p = f->pipe.file.wproc; |
p = f->pipe.file.wproc; |
ibuf = LIST_FIRST(&p->ibuflist); |
ibuf = LIST_FIRST(&p->ibuflist); |
|
|
} |
} |
|
|
/* |
/* |
* read from the socket file descriptor, fill input buffer and update |
* Read from the socket file descriptor, fill input buffer and update |
* the state. Return 1 if at least one message or 1 data byte was |
* the state. Return 1 if at least one message or 1 data byte was |
* processed, 0 if something blocked. |
* processed, 0 if something blocked. |
*/ |
*/ |
|
|
} |
} |
|
|
/* |
/* |
* process messages to return |
* Process messages to return. |
*/ |
*/ |
int |
int |
sock_return(struct sock *f) |
sock_return(struct sock *f) |
|
|
for (;;) { |
for (;;) { |
/* |
/* |
* in() may trigger rsock_done and destroy the |
* in() may trigger rsock_done and destroy the |
* wsock |
* wsock. |
*/ |
*/ |
rp = f->pipe.file.rproc; |
rp = f->pipe.file.rproc; |
if (!rp || !rp->ops->in(rp, NULL)) |
if (!rp || !rp->ops->in(rp, NULL)) |
|
|
} |
} |
|
|
/* |
/* |
* write messages and data on the socket file descriptor. Return 1 if |
* Write messages and data on the socket file descriptor. Return 1 if |
* at least one message or one data byte was processed, 0 if something |
* at least one message or one data byte was processed, 0 if something |
* blocked. |
* blocked. |
*/ |
*/ |