forked from Rosuav/shed
-
Notifications
You must be signed in to change notification settings - Fork 0
/
heryeriparlak
executable file
·137 lines (128 loc) · 4.34 KB
/
heryeriparlak
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
#!/usr/bin/env pike
//Her Yeri Parlak. Named after a dragon-killing magic item from
//Soyutlanma, this demands Combat Reflexes.
//Attempt to record and play back, without noise
//Give it a second or so of silence before anything happens.
//Will feed recorded (and noise-reduced) data to stdout,
//and will play back (unchanged) any data received on stdin.
//If given an SSH destination, will pipe itself bidirectionally
//to the given computer and attempt to invoke itself there.
/* TODO:
UDP broadcast??
Mute button??
MULTI CHANNEL????
*/
string noisemode;
int timediff;
void log(string msg)
{
werror("[%s] %s\n", gethostname(), msg);
}
array processes = ({ });
array files = ({ });
void bomb()
{
log("Child gone, terminating...");
processes->kill(2);
rm(files[*]);
exit(0);
}
Stdio.File linepipe(function handler)
{
string buf = "";
void cb(mixed id, string data)
{
buf += data;
while (has_value(buf, '\n'))
{
sscanf(buf, "%s\n%s", string line, buf);
handler(line);
}
}
object pipe = Stdio.File();
pipe->set_read_callback(cb);
return pipe->pipe();
}
void remote_stderr(string line)
{
if (line == "") return;
if (sscanf(line, "# TIMECHECK # %d", int remotetime))
{
int localtime = time();
int td = localtime - remotetime;
log(sprintf("Time here %d, there %d ==> offset %d [was %d]", localtime, remotetime, td, timediff));
timediff = td;
}
else if (line[0] != '[') werror("[remote] %s\n", line);
else werror("%s\n", line);
}
void timecheck()
{
call_out(timecheck, 30);
werror("# TIMECHECK # %d\n", time());
}
int main(int argc, array(string) argv)
{
log("Initiating Her Yeri Parlak:");
log(Process.sh_quote(argv[*]) * " ");
array(string) format = ({"-f", "s16_le", "-r", "12000"});
log("Building noise profile...");
Process.create_process(({"arecord", "-d1"}) + format + ({"/tmp/noise.wav"}), (["stderr": linepipe(log)]))->wait();
Process.create_process(({"sox", "/tmp/noise.wav", "-n", "noiseprof", "/tmp/noise.dat"}))->wait();
files += ({"/tmp/noise.wav", "/tmp/noise.dat"});
log("Noise profile built.");
object master_in=Stdio.stdin, master_out=Stdio.stdout;
noisemode = (argv[-1]/" ")[-1]; //See, this is how to get the last word in your arguments :)
if (sizeof(noisemode - "l" - "r" - "n")) noisemode = "lnln";
if (argc >= 2)
{
//SSH mode. Note that this is compatible with regular shells AND with the use
//of heryeriparlak *as* the remote shell; in the latter case, SSH will invoke
//the remote script with two arguments of "-c" and "shed/heryeriparlak -c XX"
//(where XX is the noise mode). This odd usage means that our flag for client
//mode MUST be "-c".
if (argv[1] != "-c")
{
//Establish remote link
master_in = Stdio.File(); master_out = Stdio.File();
log("Establishing link to " + argv[1]);
processes += ({
Process.create_process(({"ssh", argv[1], "shed/heryeriparlak", "-c", noisemode[2..]}),
(["stdin": master_out->pipe(), "stdout": master_in->pipe(), "stderr": linepipe(remote_stderr)])),
});
}
else call_out(timecheck, 30);
master_out->write("%2H", Stdio.read_file("/tmp/noise.dat"));
sscanf(master_in->read(2), "%2c", int len);
Stdio.write_file("/tmp/remote_noise.dat", master_in->read(len));
files += ({"/tmp/remote_noise.dat"});
int localtime = time();
master_out->write("%4c", localtime);
sscanf(master_in->read(4), "%4c", int remotetime);
timediff = localtime - remotetime;
log(sprintf("Time here %d, there %d ==> offset %d", localtime, remotetime, timediff));
}
object pipe = Stdio.File();
//All subprocesses have stderr linked to our stderr via the logger.
subprocess(0, ({"arecord", "-B", "10"}) + format, Stdio.File("/dev/null"), master_out);
subprocess(1, ({"aplay"}), master_in, Stdio.File("/dev/null", "wct"));
return -1;
}
void subprocess(int dir, array cmd, object stdin, object stdout)
{
mapping opts = (["stdin": stdin, "stdout": stdout, "stderr": linepipe(log), "callback": bomb]);
array inout = ({"stdin", "stdout"});
if (noisemode[dir] != 'n')
{
object pipe = Stdio.File();
string noisefile = noisemode[dir]=='r' ? "/tmp/remote_noise.dat" : "/tmp/noise.dat";
mapping soxopts = opts + ([inout[dir]: pipe->pipe(), inout[!dir]: opts[inout[!dir]]]);
opts[inout[!dir]] = pipe;
processes += ({
Process.create_process(({"sox", "-twav", "-", "-twav", "-", "noisered", noisefile, ".2"}), soxopts),
});
}
processes += ({
Process.create_process(cmd, opts),
});
}