Compare commits

...

4 commits
v1.4 ... master

Author SHA1 Message Date
zawz
199390d9fa update for newer ztd version 2021-08-12 18:37:44 +02:00
zawz
9efd8cf9af Output to mim format + bugfixes 2020-05-22 16:15:48 +02:00
zawz
9e984f6d38 Update to new ztd 2020-05-03 17:03:45 +02:00
zawz
df123ef150 Better help gen 2020-03-03 13:23:48 +01:00
15 changed files with 152 additions and 110 deletions

View file

@ -1,49 +1,43 @@
Device "Launch Control" Device "Launch Control"
//display value 0:127 for knobs 21-28 //display value 0:127 for knobs 21-28
Command controller Command controller
id=21:28 id=21:28
shell=echo "Knob #$id ch$channel:$value" shell='echo "Knob #$id ch$channel:$value"'
//display value 0:127 for knob 41 from any channel //display value -100:100 for knob 41 on channel 0
Command controller Command controller
id=41 id=41
channel=*
shell=echo "Knob #$id ch$channel:$value"
//display value -100:100 for knob 42 on channel 0
Command controller
id=42
channel=0 channel=0
remap=-100:100 remap=-100:100
shell=echo "Knob #$id ch0:$value r:$rawvalue" shell='echo "Knob #$id ch0:$value r:$rawvalue"'
//display value 0:1:0 for knob 42 on channel 1 (first half) //display value 0:1:0 for knob 41 on channel 1 (first half)
Command controller Command controller
id=42 id=42
channel=1 channel=1
range=0:63 range=0:63
remap=0:1 remap=0:1
float=true float=true
shell=echo "Knob #$id ch1:$value r:$rawvalue" shell='echo "Knob #$id ch1:$value r:$rawvalue"'
//display value 0:1:0 for knob 42 on channel 1 (second half) //display value 0:1:0 for knob 41 on channel 1 (second half)
Command controller Command controller
id=42 id=42
channel=1 channel=1
range=64:127 range=64:127
remap=1:0 remap=1:0
float=true float=true
shell=echo "Knob #$id ch1:$value r:$rawvalue" shell='echo "Knob #$id ch1:$value r:$rawvalue"'
Device "Launchpad S" Device "Launchpad S"
//display any note pressed and its velocity
Command note Command note
shell=echo "Note $id on velocity:$velocity" shell=echo Note $id on velocity:$velocity
//display any note off
Command note Command note
trigger=0 trigger=0
shell=echo "Note $id off" shell=echo Note $id off

View file

@ -10,46 +10,38 @@
//displays value 0:127 for knobs 21-28 //displays value 0:127 for knobs 21-28
type=controller type=controller
id=21:28 id=21:28
shell=echo "Knob #$id ch$channel:$value" shell='echo "Knob #$id ch$channel:$value"'
},
// KNOBS LOW
{
//KNOB L1
//displays value 0:127 for knob 41 from any channel
type=controller
id=41
shell=echo "Knob #$id ch$channel:$value"
}, },
{ {
//KNOB L2 //KNOB L2
//displays value -100:100 for knob 42 on channel 0 //displays value -100:100 for knob 41 on channel 0
type=controller type=controller
id=42 id=42
channel=0 channel=0
remap=-100:100 remap=-100:100
shell=echo "Knob #$id ch0:$value r:$rawvalue" shell='echo "Knob #$id ch0:$value r:$rawvalue"'
}, },
{ {
//KNOB L3 H1 //KNOB L3 H1
//displays value 0:1:0 for knob 42 on channel 1 (first half) //displays value 0:1:0 for knob 41 on channel 1 (first half)
type=controller type=controller
id=42 id=42
channel=1 channel=1
range=0:63 range=0:63
remap=0:1 remap=0:1
float=true float=true
shell=echo "Knob #$id ch1:$value r:$rawvalue" shell='echo "Knob #$id ch1:$value r:$rawvalue"'
}, },
{ {
//KNOB L3 H2 //KNOB L3 H2
//displays value 0:1:0 for knob 42 on channel 1 (second half) //displays value 0:1:0 for knob 41 on channel 1 (second half)
type=controller type=controller
id=42 id=42
channel=1 channel=1
range=64:127 range=64:127
remap=1:0 remap=1:0
float=true float=true
shell=echo "Knob #$id ch1:$value r:$rawvalue" shell='echo "Knob #$id ch1:$value r:$rawvalue"'
} }
] ]
} }
@ -61,13 +53,13 @@
{ {
// ANY NOTE ON // ANY NOTE ON
type=note type=note
shell=echo "Note $id on velocity:$velocity" shell=echo Note $id on velocity:$velocity
}, },
{ {
// ANY NOTE OFF // ANY NOTE OFF
type=note type=note
trigger=0 trigger=0
shell=echo "Note $id off" shell=echo Note $id off
} }
] ]
} }

View file

@ -1,11 +1,38 @@
FORMAT_FOLDER=help_format FORMAT_FOLDER=help_format
IDIR=include IDIR=include
cp $FORMAT_FOLDER/help_template_head $IDIR/help.h SLASHSCRIPT='s|\\|\\\\|g;s|\"|\\\"|g'
NEWLINESCRIPT=':a;N;$!ba;s/\n/\\n/g;'
echo "#define ZFD_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/zfd-format)\"" >> $IDIR/help.h filetocstr()
echo "#define MIM_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/mim-format)\"" >> $IDIR/help.h {
echo "#define SHELL_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/shell-format)\"" >> $IDIR/help.h sed -e $SLASHSCRIPT "$1" | sed $NEWLINESCRIPT
echo "#define COMMAND_TAGS \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/command-tags)\"" >> $IDIR/help.h }
cat $FORMAT_FOLDER/help_template_tail >> $IDIR/help.h gen_line()
{
name="$(basename "$1")"
echo "#define $(echo "$name" | tr '[:lower:]' '[:upper:]') \"$(filetocstr "$1")\""
}
help_header()
{
echo '#ifndef HELP_H
#define HELP_
'
}
help_footer()
{
echo '
#endif //HELP_H'
}
help_header > "$IDIR/help.h"
for I in help_format/*
do
gen_line "$I" >> "$IDIR/help.h"
done
help_footer >> "$IDIR/help.h"

View file

@ -1,2 +0,0 @@
#ifndef HELP_H
#define HELP_H

View file

@ -1 +0,0 @@
#endif //HELP_H

View file

@ -20,7 +20,7 @@ Device <name>
*shell: shell command to be executed *shell: shell command to be executed
> mandatory > mandatory
Shell command can be concatenated with \"\" or '' Shell commands can be concatenated with "" or ''
Comments are written with // or # and end at end of line Comments are written with // or # and end at end of line
Multiple tags can be put on the same line by separating them with ; Multiple tags can be put on the same line by separating them with ;
See --command-tags for optional command tags See --command-tags for optional command tags

View file

@ -26,5 +26,5 @@ ZFD format: http://zawz.net/doc/ztd/zfd.html
*shell: shell command to be executed *shell: shell command to be executed
> mandatory > mandatory
Shell command can be concatenated with \"\" or '' Shell commands can be concatenated with "" or ''
see --command-tags for optional command tags see --command-tags for optional command tags

View file

@ -5,6 +5,8 @@
ztd::chunkdat mimtochk(std::string mim); ztd::chunkdat mimtochk(std::string mim);
std::string chktomim(ztd::chunkdat const& chk, std::string const& aligner);
std::string file_strimport(const std::string& path); std::string file_strimport(const std::string& path);
bool is_mim(const std::string& str); bool is_mim(const std::string& str);

View file

@ -1,7 +1,9 @@
#ifndef HELP_H #ifndef HELP_H
#define HELP_H #define HELP_
#define ZFD_FORMAT "zmidimap\n-- [ZFD FILE FORMAT] --\n\nZFD format: http://zawz.net/doc/ztd/zfd.html\n\n[<device>,<device>]\n\n-- <device> format --\n {\n name=<name>\n commands=[<command>,<command>]\n }\n--\n*name: string referring to client name of the device\n\n<command> format\n {\n type=<type>\n shell=<shell command>\n <tag>=<value>\n <tag>=<value>\n ...\n }\n--\n*type: type of the signal: note/controller/pitch/system/connect/disconnect\n > mandatory\n*shell: shell command to be executed\n > mandatory\n\nShell command can be concatenated with \"\" or ''\nsee --command-tags for optional command tags"
#define MIM_FORMAT "zmidimap\n-- [MIM FILE FORMAT] --\n\nDevice <name>\n Command <type>\n shell=<shell command>\n <tag>=<value>\n <tag>=<value>\n ...\n Command <type>\n ...\n\nDevice <name>\n...\n\n--\n*name: string referring to client name of the device\n > mandatory\n*type: type of the signal: note/controller/pitch/system/connect/disconnect\n > mandatory\n*shell: shell command to be executed\n > mandatory\n\nShell command can be concatenated with \"\" or ''\nComments are written with // or # and end at end of line\nMultiple tags can be put on the same line by separating them with ;\nSee --command-tags for optional command tags" #define COMMAND_TAGS "-- [COMMAND TAGS] --\n\n[Note tags]\n id=<interval>\n channel=<x/*>\n trigger=<interval>\n--\n *id: note id from 0 to 127\n > optional, default 0:127\n *channel: value from 0 to 16 for channel, * for any channel\n > optional, default *\n *trigger: note velocity from 0 to 127 that triggers the command\n > optional, default 1:127\n\n[Controller tags]\n id=<interval>\n channel=<x/*>\n range=<interval>\n remap=<interval>\n float=<true/false>\n--\n *id: controller id from 0 to 127\n > optional, default 0:127\n *channel: value from 0 to 16 for channel, * for any channel\n > optional, default *\n *range: controller value from 0 to 127 that triggers command\n > optional, default 0:127\n *remap: remaps the range to given interval\n > optional, default same as range\n *float: boolean value defining if output is a floating point value\n > optional, default false\n\n[Pitch bend tags]\n range=<interval>\n remap=<interval>\n float=<true/false>\n--\n *range: controller value from -8192 to 8191 that triggers command\n > optional, default -8192:8191\n *remap: remaps the range to given interval\n > optional, default same as range\n *float: boolean value defining if output is a floating point value\n > optional, default false\n\n[Interval Format]\n x:y range from x to y\n x single value x\n * all possible values"
#define SHELL_FORMAT "zmidimap\n-- [SHELL FORMAT] --\n\nShell command follows regular shell format\n\n-- [Environment] --\n\n[Note]\n $id: id of the note\n $channel: channel of the note\n $velocity: velocity of the note\n\n[Controller]\n $value: value of the controller (remapped)\n $id: id of the controller\n $channel: channel of the controller\n $rawvalue: original value of the controller\n\n[Pitch]\n $value: value of the bend (remapped)\n $rawvalue: original value of the bend\n\n[System]\n $code: hexadecimal code of the system signal" #define MIM_FORMAT "-- [MIM FILE FORMAT] --\n\nDevice <name>\n Command <type>\n shell=<shell command>\n <tag>=<value>\n <tag>=<value>\n ...\n Command <type>\n ...\n\nDevice <name>\n...\n\n--\n*name: string referring to client name of the device\n > mandatory\n*type: type of the signal: note/controller/pitch/system/connect/disconnect\n > mandatory\n*shell: shell command to be executed\n > mandatory\n\nShell commands can be concatenated with \"\" or ''\nComments are written with // or # and end at end of line\nMultiple tags can be put on the same line by separating them with ;\nSee --command-tags for optional command tags"
#define COMMAND_TAGS "zmidimap\n-- [COMMAND TAGS] --\n\n[Note tags]\n id=<interval>\n channel=<x/*>\n trigger=<interval>\n--\n *id: note id from 0 to 127\n > optional, default 0:127\n *channel: value from 0 to 16 for channel, * for any channel\n > optional, default *\n *trigger: note velocity from 0 to 127 that triggers the command\n > optional, default 1:127\n\n[Controller tags]\n id=<interval>\n channel=<x/*>\n range=<interval>\n remap=<interval>\n float=<true/false>\n--\n *id: controller id from 0 to 127\n > optional, default 0:127\n *channel: value from 0 to 16 for channel, * for any channel\n > optional, default *\n *range: controller value from 0 to 127 that triggers command\n > optional, default 0:127\n *remap: remaps the range to given interval\n > optional, default same as range\n *float: boolean value defining if output is a floating point value\n > optional, default false\n\n[Pitch bend tags]\n range=<interval>\n remap=<interval>\n float=<true/false>\n--\n *range: controller value from -8192 to 8191 that triggers command\n > optional, default -8192:8191\n *remap: remaps the range to given interval\n > optional, default same as range\n *float: boolean value defining if output is a floating point value\n > optional, default false\n\n[Interval Format]\n x:y range from x to y\n x single value x\n * all possible values" #define SHELL_FORMAT "-- [SHELL FORMAT] --\n\nShell command follows regular shell format\n\n-- [Environment] --\n\n[Note]\n $id: id of the note\n $channel: channel of the note\n $velocity: velocity of the note\n\n[Controller]\n $value: value of the controller (remapped)\n $id: id of the controller\n $channel: channel of the controller\n $rawvalue: original value of the controller\n\n[Pitch]\n $value: value of the bend (remapped)\n $rawvalue: original value of the bend\n\n[System]\n $code: hexadecimal code of the system signal"
#define ZFD_FORMAT "-- [ZFD FILE FORMAT] --\n\nZFD format: http://zawz.net/doc/ztd/zfd.html\n\n[<device>,<device>]\n\n-- <device> format --\n {\n name=<name>\n commands=[<command>,<command>]\n }\n--\n*name: string referring to client name of the device\n\n<command> format\n {\n type=<type>\n shell=<shell command>\n <tag>=<value>\n <tag>=<value>\n ...\n }\n--\n*type: type of the signal: note/controller/pitch/system/connect/disconnect\n > mandatory\n*shell: shell command to be executed\n > mandatory\n\nShell commands can be concatenated with \"\" or ''\nsee --command-tags for optional command tags"
#endif //HELP_H #endif //HELP_H

View file

@ -286,7 +286,7 @@ void Device::run_signal(char* buff)
{ {
std::string command="code=" + strval + ";"; std::string command="code=" + strval + ";";
command += dequote(it.shell); command += dequote(it.shell);
std::thread(ztd::sh, command, true).detach(); std::thread(ztd::shr, command).detach();
} }
} }
else else
@ -363,7 +363,7 @@ void Device::run_signal(char* buff)
+ ";channel=" + std::to_string(channel) + ";channel=" + std::to_string(channel)
+ ";velocity=" + std::to_string(value) + ";"; + ";velocity=" + std::to_string(value) + ";";
command += dequote(it.shell); command += dequote(it.shell);
std::thread(ztd::sh, command, true).detach(); std::thread(ztd::shr, command).detach();
} }
} }
} }
@ -390,7 +390,7 @@ void Device::run_signal(char* buff)
else else
command += std::to_string((long int) result); command += std::to_string((long int) result);
command += ";" + dequote(it.shell); command += ";" + dequote(it.shell);
std::thread(ztd::sh, command, true).detach(); std::thread(ztd::shr, command).detach();
} }
} }
} }
@ -416,7 +416,7 @@ void Device::run_signal(char* buff)
else else
command += std::to_string((long int) result); command += std::to_string((long int) result);
command += ";" + dequote(it.shell); command += ";" + dequote(it.shell);
std::thread(ztd::sh, command, true).detach(); std::thread(ztd::shr, command).detach();
} }
} }
} // if type } // if type
@ -438,7 +438,7 @@ void Device::loop(Device* dev)
for( auto it : dev->connectCommands ) for( auto it : dev->connectCommands )
{ {
std::thread(ztd::sh, dequote(it.shell), true).detach(); std::thread(ztd::shr, dequote(it.shell)).detach();
} }
while (getline(&buff, &buff_size, stream) > 0) while (getline(&buff, &buff_size, stream) > 0)
@ -448,7 +448,7 @@ void Device::loop(Device* dev)
for( auto it : dev->disconnectCommands ) for( auto it : dev->disconnectCommands )
{ {
std::thread(ztd::sh, dequote(it.shell), true).detach(); std::thread(ztd::shr, dequote(it.shell)).detach();
} }
log("Device '" + dev->name + "' disconnected\n"); log("Device '" + dev->name + "' disconnected\n");

View file

@ -98,6 +98,29 @@ ztd::chunkdat mimtochk(std::string mim)
return chk; return chk;
} }
std::string chktomim(ztd::chunkdat const& chk, std::string const& aligner)
{
std::string ret;
for(int i=0 ; i<chk.listSize() ; i++)
{
ztd::chunkdat& device=chk[i];
ret += "Device " + device.subChunkRef("name").str() + "\n\n";
for(int j=0 ; j < device["commands"].listSize() ; j++)
{
ztd::chunkdat command=device["commands"][j];
ret += aligner + "Command " + command["type"].str() + '\n';
command.erase("type");
for(auto it : command.getmap())
{
ret += aligner+aligner + it.first + '=' + it.second->str() + '\n';
}
ret += '\n';
// ret += command.str(2, aligner) + '\n';
}
}
return ret;
}
bool is_mim(const std::string& str) bool is_mim(const std::string& str)
{ {
unsigned int i=0; unsigned int i=0;

View file

@ -75,11 +75,11 @@ void load_filedat(ztd::filedat& file, bool from_stdin, std::string const& path)
file.setFilePath(path); file.setFilePath(path);
std::string str=file_strimport(path); std::string str=file_strimport(path);
if(options.find("zfd")->activated) if(options["zfd"])
{ {
file.data() = str; file.data() = str;
} }
else if(options.find("mim")->activated) else if(options["mim"])
{ {
file.data() = mimtochk(str); file.data() = mimtochk(str);
} }
@ -100,11 +100,11 @@ void load_filedat(ztd::filedat& file, bool from_stdin, std::string const& path)
{ {
file.setFilePath(path); file.setFilePath(path);
log("Loading map file '" + path + "'\n"); log("Loading map file '" + path + "'\n");
if(options.find("zfd")->activated) if(options["zfd"])
{ {
file.import_file(); file.import_file();
} }
else if(options.find("mim")->activated) else if(options["mim"])
{ {
file.data() = mimtochk(file_strimport(path)); file.data() = mimtochk(file_strimport(path));
} }
@ -143,29 +143,28 @@ int main(int argc, char* argv[])
bool autoreload=true; bool autoreload=true;
bool from_stdin=false; bool from_stdin=false;
options.add(ztd::option("\r [Help]")); options.add(
options.add(ztd::option('h',"help", false, "Display this help message")); ztd::option("\r [Help]"),
options.add(ztd::option('v',"version", false, "Display version")); ztd::option('h',"help", false, "Display this help message"),
options.add(ztd::option("mim-format", false, "Display mim file format help")); ztd::option('v',"version", false, "Display version"),
options.add(ztd::option("zfd-format", false, "Display zfd file format help")); ztd::option("mim-format", false, "Display mim file format help"),
options.add(ztd::option("command-tags", false, "Display for command tag help")); ztd::option("zfd-format", false, "Display zfd file format help"),
options.add(ztd::option("shell-format", false, "Display for shell format help")); ztd::option("command-tags", false, "Display for command tag help"),
ztd::option("shell-format", false, "Display for shell format help"),
options.add(ztd::option("\r [Format]")); ztd::option("\r [Format]"),
options.add(ztd::option("no-log", false, "Disable console logging")); ztd::option("no-log", false, "Disable console logging"),
ztd::option("\r [Devices]"),
options.add(ztd::option("\r [Devices]")); ztd::option('l',"list", false, "List detected devices"),
options.add(ztd::option('l',"list", false, "List detected devices")); ztd::option('L',"full-list", false, "Print whole device list details"),
options.add(ztd::option('L',"full-list", false, "Print whole device list details")); ztd::option('p',"port", true, "Connect to device and output to console", "device"),
options.add(ztd::option('p',"port", true, "Connect to device and output to console", "device")); ztd::option("\r [Map file]"),
options.add(ztd::option("\r [Map file]")); ztd::option('m',"mim", false, "Read file in mim format"),
options.add(ztd::option('m',"mim", false, "Read file in mim format")); ztd::option('z',"zfd", false, "Read file in zfd format"),
options.add(ztd::option('z',"zfd", false, "Read file in zfd format")); ztd::option('o',"output", true, "Output the resulting map to file", "file"),
options.add(ztd::option('o',"output", true, "Output the resulting zfd map to file. - for stdout", "file")); ztd::option("out-zfd", false, "Output in zfd format"),
options.add(ztd::option("aligner", true, "String to use for aligning output map format. Default \\t", "string")); ztd::option("aligner", true, "String to use for aligning output map format. Default \\t", "string"),
options.add(ztd::option("no-reload", false, "Disable auto reloading when file changes are detected")); ztd::option("no-reload", false, "Disable auto reloading when file changes are detected")
options.add(ztd::option("\rIf no file format is specified, the program will try to guess the format")); );
// options.add(ztd::option('i',"interactive", false, "Start in interactive mode"));
std::vector<std::string> arg; std::vector<std::string> arg;
try try
@ -180,74 +179,72 @@ int main(int argc, char* argv[])
stop(1); stop(1);
} }
ztd::option* op=nullptr;
//exit options //exit options
if( options.find('h')->activated ) if( options['h'] )
{ {
help(); help();
stop(0); stop(0);
} }
if( options.find('v')->activated ) if( options['v'] )
{ {
version(); version();
stop(0); stop(0);
} }
if( options.find("mim-format")->activated ) if( options["mim-format"] )
{ {
printf("%s\n", MIM_FORMAT); printf("%s\n", MIM_FORMAT);
stop(0); stop(0);
} }
if( options.find("zfd-format")->activated ) if( options["zfd-format"] )
{ {
printf("%s\n", ZFD_FORMAT); printf("%s\n", ZFD_FORMAT);
stop(0); stop(0);
} }
if( options.find("command-tags")->activated ) if( options["command-tags"] )
{ {
printf("%s\n", COMMAND_TAGS); printf("%s\n", COMMAND_TAGS);
stop(0); stop(0);
} }
if( options.find("shell-format")->activated ) if( options["shell-format"] )
{ {
printf("%s\n", SHELL_FORMAT); printf("%s\n", SHELL_FORMAT);
stop(0); stop(0);
} }
if( options.find('L')->activated ) if( options['L'] )
{ {
ztd::sh("aseqdump -l", true); ztd::shr("aseqdump -l");
stop(0); stop(0);
} }
if( options.find('l')->activated ) if( options['l'] )
{ {
ztd::sh(LIST_COMMAND, true); ztd::shr(LIST_COMMAND);
stop(0); stop(0);
} }
op = options.find('p'); if( options['p'] )
if( op->activated )
{ {
option_p(op->argument); option_p(options['p']);
stop(0); stop(0);
} }
if (options.find('o')->activated) if (options['o'])
{ {
log_on=false; log_on=false;
} }
//behavioral options //behavioral options
if( options.find("no-reload")->activated ) if( options["no-reload"] )
{ {
autoreload=false; autoreload=false;
} }
if( options.find("no-log")->activated ) if( options["no-log"] )
{ {
log_on=false; log_on=false;
} }
std::string aligner="\t"; std::string aligner="\t";
if(options.find("aligner")->activated) if(options["aligner"])
{ {
aligner=options.find("aligner")->argument; aligner=options["aligner"].argument;
} }
//no argument: display help //no argument: display help
@ -274,14 +271,24 @@ int main(int argc, char* argv[])
//load //load
load_filedat(file, from_stdin, filepath); load_filedat(file, from_stdin, filepath);
//output //output
if(options.find('o')->activated) if(options['o'])
{ {
if(options.find('o')->argument == "-") { std::string ret;
std::cout << file.strval(aligner) << std::endl; if(options["out-zfd"])
ret=file.data().str(0, aligner);
else
ret=chktomim(file.data(), aligner);
if(options['o'].argument == "-") {
std::cout << ret << std::endl;
} }
else { else {
file.setFilePath(options.find('o')->argument); std::ofstream output(options['o']);
file.export_file(); if(!output)
{
std::cerr << "Cannot write to file '" + options['o'].argument + "'\n";
return 1;
}
output << ret << std::endl ;
} }
return 0; return 0;
} }

View file

@ -96,9 +96,7 @@ void announce_loop()
device_check(); device_check();
} }
int ret = WEXITSTATUS(ztd::pclose2(stream, announce_thread_pid)); ztd::pclose2(stream, announce_thread_pid);
if( ret != 0 )
throw std::runtime_error("ALSA error");
if(buff != NULL) if(buff != NULL)
free(buff); free(buff);