1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
typedef struct Worker Worker;
typedef struct Req Req;
typedef struct Fid Fid;
typedef struct File File;
typedef struct Playlist Playlist;
typedef struct Wmsg Wmsg;
typedef union Pmsg Pmsg;
typedef struct Pacbuf Pacbuf;
enum {
Qdir,
Qplayctl,
Qplaylist,
Qplayvol,
Qplaystat,
Nqid,
};
enum {
DbgPcm = 0x01000,
DbgPac = 0x02000,
DbgFs = 0x10000,
DbgWorker = 0x20000,
DbgPlayer = 0x40000,
DbgError = 0x80000,
};
enum {
Messagesize = 8*1024+IOHDRSZ,
Undef = 0x80000000,
/* 256 buffers of 4096 bytes represents 5.9 seconds
* of playout at 44100 Hz (2*16bit samples)
*/
NPacbuf = 256,
Pacbufsize = 4096,
NSparebuf = 16, /* For in-line commands (Pause, Resume, Error) */
};
enum {
/* Named commands (see fs.c): */
Nostate, // can't use zero for state
Error,
Stop,
Pause,
Play,
Resume,
Skip,
/* Unnamed commands */
Work,
Check,
Flush,
Prep,
Preq,
};
union Pmsg {
ulong m;
struct{
ushort cmd;
ushort off;
};
};
struct Wmsg {
Pmsg;
void *arg; /* if(cmd != Work) mallocated by sender, freed by receiver */
};
struct Playlist {
/* The play list consists of a sequence of {objectref, filename}
* entries. Object ref and file name are separated by a tab.
* An object ref may not contain a tab. Entries are seperated
* by newline characters. Neither file names, nor object refs
* may contain newlines.
*/
ulong *lines;
ulong nlines;
char *data;
ulong ndata;
};
struct File {
Dir dir;
Channel *workers;
};
struct Worker
{
Req *r;
Channel *eventc;
};
struct Fid
{
int fid;
File *file;
ushort flags;
short readers;
ulong vers; /* set to file's version when completely read */
Fid *next;
};
struct Req
{
uchar indata[Messagesize];
uchar outdata[Messagesize];
Fcall ifcall;
Fcall ofcall;
Fid* fid;
};
struct Pacbuf {
Pmsg;
int len;
char data[Pacbufsize];
};
void allocwork(Req*);
Wmsg waitmsg(Worker*, Channel*);
int sendmsg(Channel*, Wmsg*);
void bcastmsg(Channel*, Wmsg*);
void reqfree(Req*);
Req *reqalloc(void);
void readbuf(Req*, void*, long);
void readstr(Req*, char*);
void volumeset(int *v);
void playupdate(Pmsg, char*);
void playinit(void);
void volumeproc(void*);
void srv(void *);
long robustread(int, void*, long);
void volumeupdate(int*);
char *getplaylist(int);
char *getplaystat(char*, char*);
extern int debug, aflag;
extern char *user;
extern Channel *playc;
extern char *statetxt[];
extern int volume[8];
extern Playlist playlist;
extern Channel *workers;
extern Channel *volumechan;
extern Channel *playchan;
extern Channel *playlistreq;
extern File files[];
extern int srvfd[];
|