Compare commits
No commits in common. "master" and "v1.2.1" have entirely different histories.
20 changed files with 196 additions and 354 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
zmidimap
|
|
||||||
obj
|
|
||||||
Zmakefile
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -11,8 +11,6 @@ CC=g++
|
||||||
CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++17
|
CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++17
|
||||||
ifeq ($(DEBUG),true)
|
ifeq ($(DEBUG),true)
|
||||||
CXXFLAGS += -g
|
CXXFLAGS += -g
|
||||||
else
|
|
||||||
CXXFLAGS += -O2
|
|
||||||
endif
|
endif
|
||||||
ifeq ($(STATIC),true)
|
ifeq ($(STATIC),true)
|
||||||
LDFLAGS += -l:libztd.a
|
LDFLAGS += -l:libztd.a
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Map midi signals coming from ALSA midi devices to shell commands
|
Map midi signals coming from ALSA midi devices to shell commands
|
||||||
|
|
||||||
Dependencies: alsa-utils
|
Dependencies: alsa-utils , [ztd](https://github.com/zawwz/ztd)
|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
|
|
@ -14,12 +14,10 @@ Download the .deb package then run: `sudo dpkg -i zmidimap.deb ; sudo apt -f ins
|
||||||
|
|
||||||
### Standalone
|
### Standalone
|
||||||
|
|
||||||
Download ``zmidimap.tar.gz`` for a standalone executable
|
Download ``zmidimap-static.tar.gz`` for a standalone executable without library dependency
|
||||||
|
|
||||||
### From source
|
### From source
|
||||||
|
|
||||||
Depends on: [ztd](https://github.com/zawwz/ztd)
|
|
||||||
|
|
||||||
``make -j6`` for a shared build
|
``make -j6`` for a shared build
|
||||||
``STATIC=true make -j6`` for a static build
|
``STATIC=true make -j6`` for a static build
|
||||||
|
|
||||||
|
|
|
||||||
28
example.mim
28
example.mim
|
|
@ -1,43 +1,49 @@
|
||||||
|
|
||||||
|
|
||||||
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 -100:100 for knob 41 on channel 0
|
//display value 0:127 for knob 41 from any channel
|
||||||
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 41 on channel 1 (first half)
|
//display value 0:1:0 for knob 42 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 41 on channel 1 (second half)
|
//display value 0:1:0 for knob 42 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"
|
||||||
|
|
|
||||||
26
example.zfd
26
example.zfd
|
|
@ -10,38 +10,46 @@
|
||||||
//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 41 on channel 0
|
//displays value -100:100 for knob 42 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 41 on channel 1 (first half)
|
//displays value 0:1:0 for knob 42 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 41 on channel 1 (second half)
|
//displays value 0:1:0 for knob 42 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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -53,13 +61,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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,11 @@
|
||||||
FORMAT_FOLDER=help_format
|
FORMAT_FOLDER=help_format
|
||||||
IDIR=include
|
IDIR=include
|
||||||
|
|
||||||
SLASHSCRIPT='s|\\|\\\\|g;s|\"|\\\"|g'
|
cp $FORMAT_FOLDER/help_template_head $IDIR/help.h
|
||||||
NEWLINESCRIPT=':a;N;$!ba;s/\n/\\n/g;'
|
|
||||||
|
|
||||||
filetocstr()
|
echo "#define ZFD_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/zfd-format)\"" >> $IDIR/help.h
|
||||||
{
|
echo "#define MIM_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/mim-format)\"" >> $IDIR/help.h
|
||||||
sed -e $SLASHSCRIPT "$1" | sed $NEWLINESCRIPT
|
echo "#define SHELL_FORMAT \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/shell-format)\"" >> $IDIR/help.h
|
||||||
}
|
echo "#define COMMAND_TAGS \"zmidimap$(sed -n -e 'H;${x;s/\n/\\n/g;s/^,//;p;}' $FORMAT_FOLDER/command-tags)\"" >> $IDIR/help.h
|
||||||
|
|
||||||
gen_line()
|
cat $FORMAT_FOLDER/help_template_tail >> $IDIR/help.h
|
||||||
{
|
|
||||||
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"
|
|
||||||
|
|
|
||||||
2
help_format/help_template_head
Normal file
2
help_format/help_template_head
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
#ifndef HELP_H
|
||||||
|
#define HELP_H
|
||||||
1
help_format/help_template_tail
Normal file
1
help_format/help_template_tail
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#endif //HELP_H
|
||||||
|
|
@ -20,7 +20,6 @@ Device <name>
|
||||||
*shell: shell command to be executed
|
*shell: shell command to be executed
|
||||||
> mandatory
|
> mandatory
|
||||||
|
|
||||||
Shell commands can be concatenated with "" or ''
|
Shell command can be concatenated with \"\" or ''
|
||||||
Comments are written with // or # and end at end of line
|
Comments are written by starting a line 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
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
-- [ZFD FILE FORMAT] --
|
-- [ZFD FILE FORMAT] --
|
||||||
|
|
||||||
ZFD format: http://zawz.net/doc/ztd/zfd.html
|
|
||||||
|
|
||||||
[<device>,<device>]
|
[<device>,<device>]
|
||||||
|
|
||||||
-- <device> format --
|
-- <device> format --
|
||||||
|
|
@ -26,5 +24,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 commands can be concatenated with "" or ''
|
Shell command can be concatenated with \"\" or ''
|
||||||
see --command-tags for optional command tags
|
see --command-tags for optional command tags
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include <ztd/filedat.hpp>
|
#include <ztd/filedat.hpp>
|
||||||
|
|
||||||
|
void sh(std::string const& string);
|
||||||
|
|
||||||
class Device
|
class Device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -17,7 +19,7 @@ public:
|
||||||
bool start_loop();
|
bool start_loop();
|
||||||
void run_signal(char* buff);
|
void run_signal(char* buff);
|
||||||
|
|
||||||
bool import_chunk(const ztd::chunkdat& ch);
|
bool import_chunk(ztd::chunkdat const& ch);
|
||||||
ztd::chunkdat export_chunk();
|
ztd::chunkdat export_chunk();
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
@ -32,6 +34,7 @@ public:
|
||||||
std::vector<ConnectCommand> connectCommands;
|
std::vector<ConnectCommand> connectCommands;
|
||||||
std::vector<DisconnectCommand> disconnectCommands;
|
std::vector<DisconnectCommand> disconnectCommands;
|
||||||
|
|
||||||
|
std::thread thread;
|
||||||
pid_t thread_pid;
|
pid_t thread_pid;
|
||||||
private:
|
private:
|
||||||
static void loop(Device* dev);
|
static void loop(Device* dev);
|
||||||
|
|
@ -39,6 +42,4 @@ private:
|
||||||
|
|
||||||
extern std::vector<Device*> device_list;
|
extern std::vector<Device*> device_list;
|
||||||
|
|
||||||
void clean_devices();
|
|
||||||
|
|
||||||
#endif //DEVICE_HPP
|
#endif //DEVICE_HPP
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,7 @@
|
||||||
|
|
||||||
#include <ztd/filedat.hpp>
|
#include <ztd/filedat.hpp>
|
||||||
|
|
||||||
ztd::chunkdat mimtochk(std::string mim);
|
ztd::chunkdat mimtochk(const 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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
#ifndef HELP_H
|
#ifndef HELP_H
|
||||||
#define HELP_
|
#define HELP_H
|
||||||
|
#define ZFD_FORMAT "zmidimap\n-- [ZFD FILE FORMAT] --\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 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 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\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 ''\nsee --command-tags for optional command tags"
|
||||||
#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 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 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 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 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
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,10 @@
|
||||||
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
#define LIST_COMMAND "aseqdump -l | tail -n +2 | cut -c10-42 | tr -s ' '"
|
||||||
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
#define LIST_EXTENDED_COMMAND "aseqdump -l | tail -n +2 | cut -c-42"
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
extern int announce_thread_pid;
|
extern int announce_thread_pid;
|
||||||
|
|
||||||
void kill_all();
|
|
||||||
|
|
||||||
void device_check();
|
void device_check();
|
||||||
|
|
||||||
void announce_loop();
|
void announce_loop();
|
||||||
|
|
||||||
void filetime_loop(std::string const& filepath);
|
|
||||||
|
|
||||||
#endif //SYSTEM_HPP
|
#endif //SYSTEM_HPP
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <ztd/shell.hpp>
|
#include <ztd/shell.hpp>
|
||||||
|
|
||||||
#include "log.hpp"
|
#include "log.hpp"
|
||||||
|
|
@ -36,11 +35,16 @@ static std::string dequote(const std::string& in)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _isNum(const char& a)
|
static bool _isNum(char a)
|
||||||
{
|
{
|
||||||
return (a>='0' && a<='9');
|
return (a>='0' && a<='9');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sh(std::string const& string)
|
||||||
|
{
|
||||||
|
system(string.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
Device::Device()
|
Device::Device()
|
||||||
{
|
{
|
||||||
busy=false;
|
busy=false;
|
||||||
|
|
@ -59,16 +63,17 @@ bool Device::start_loop()
|
||||||
if(this->busy)
|
if(this->busy)
|
||||||
return false;
|
return false;
|
||||||
this->busy = true;
|
this->busy = true;
|
||||||
std::thread(Device::loop, this).detach();
|
this->thread = std::thread(Device::loop, this);
|
||||||
|
this->thread.detach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int32_t,int32_t> importRange(const ztd::chunkdat& ch, const std::string& tag, int32_t low, int32_t high)
|
std::pair<int32_t,int32_t> importRange(ztd::chunkdat const& ch, std::string const& tag, int32_t low, int32_t high)
|
||||||
{
|
{
|
||||||
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=*pch;
|
std::string str=pch->strval();
|
||||||
auto tpos=str.find(':');
|
auto tpos=str.find(':');
|
||||||
if (str=="*") //whole range
|
if (str=="*") //whole range
|
||||||
{
|
{
|
||||||
|
|
@ -76,25 +81,25 @@ std::pair<int32_t,int32_t> importRange(const ztd::chunkdat& ch, const std::strin
|
||||||
}
|
}
|
||||||
else if(tpos == std::string::npos) //single value
|
else if(tpos == std::string::npos) //single value
|
||||||
{
|
{
|
||||||
low=std::stoi(str);
|
low=stoi(str);
|
||||||
high=low;
|
high=low;
|
||||||
}
|
}
|
||||||
else //range
|
else //range
|
||||||
{
|
{
|
||||||
low=std::stoi(str.substr(0,tpos));
|
low=stoi(str.substr(0,tpos));
|
||||||
tpos++;
|
tpos++;
|
||||||
high=std::stoi(str.substr(tpos, str.size()-tpos));
|
high=stoi(str.substr(tpos, str.size()-tpos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::make_pair(low, high);
|
return std::make_pair(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<float,float> importRangeFloat(const ztd::chunkdat& ch, const std::string& tag, float low, float high)
|
std::pair<float,float> importRangeFloat(ztd::chunkdat const& ch, std::string const& tag, float low, float high)
|
||||||
{
|
{
|
||||||
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=*pch;
|
std::string str=pch->strval();
|
||||||
auto tpos=str.find(':');
|
auto tpos=str.find(':');
|
||||||
if(tpos == std::string::npos)
|
if(tpos == std::string::npos)
|
||||||
{
|
{
|
||||||
|
|
@ -113,12 +118,12 @@ std::pair<float,float> importRangeFloat(const ztd::chunkdat& ch, const std::stri
|
||||||
return std::make_pair(low, high);
|
return std::make_pair(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool importBool(const ztd::chunkdat& ch, const std::string& tag, const bool& defbool)
|
bool importBool(ztd::chunkdat const& ch, std::string const& tag, bool defbool)
|
||||||
{
|
{
|
||||||
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
ztd::chunkdat* pch=ch.subChunkPtr(tag);
|
||||||
if(pch != nullptr)
|
if(pch != nullptr)
|
||||||
{
|
{
|
||||||
std::string str=*pch;
|
std::string str=pch->strval();
|
||||||
if( str == "true" )
|
if( str == "true" )
|
||||||
return true;
|
return true;
|
||||||
else if( str == "false" )
|
else if( str == "false" )
|
||||||
|
|
@ -127,30 +132,30 @@ bool importBool(const ztd::chunkdat& ch, const std::string& tag, const bool& def
|
||||||
return defbool;
|
return defbool;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Device::import_chunk(const ztd::chunkdat& ch)
|
bool Device::import_chunk(ztd::chunkdat const& ch)
|
||||||
{
|
{
|
||||||
ztd::chunkdat& cch = ch["commands"];
|
ztd::chunkdat& cch = ch["commands"];
|
||||||
this->name=dequote(ch["name"]);
|
this->name=dequote(ch["name"].strval());
|
||||||
for(int i=0 ; i<cch.listSize() ; i++)
|
for(int i=0 ; i<cch.listSize() ; i++)
|
||||||
{
|
{
|
||||||
ztd::chunkdat& tch=cch[i];
|
ztd::chunkdat& tch=cch[i];
|
||||||
std::string tstr=tch["type"];
|
std::string tstr=tch["type"].strval();
|
||||||
if(tstr == "system") //type system
|
if(tstr == "system") //type system
|
||||||
{
|
{
|
||||||
std::string shell;
|
std::string shell;
|
||||||
shell=tch["shell"];
|
shell=tch["shell"].strval();
|
||||||
this->sysCommands.push_back(SystemCommand(shell));
|
this->sysCommands.push_back(SystemCommand(shell));
|
||||||
}
|
}
|
||||||
else if (tstr == "connect")
|
else if (tstr == "connect")
|
||||||
{
|
{
|
||||||
std::string shell;
|
std::string shell;
|
||||||
shell=tch["shell"];
|
shell=tch["shell"].strval();
|
||||||
this->connectCommands.push_back(ConnectCommand(shell));
|
this->connectCommands.push_back(ConnectCommand(shell));
|
||||||
}
|
}
|
||||||
else if (tstr == "disconnect")
|
else if (tstr == "disconnect")
|
||||||
{
|
{
|
||||||
std::string shell;
|
std::string shell;
|
||||||
shell=tch["shell"];
|
shell=tch["shell"].strval();
|
||||||
this->disconnectCommands.push_back(DisconnectCommand(shell));
|
this->disconnectCommands.push_back(DisconnectCommand(shell));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -162,13 +167,13 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
std::pair<float,float> floatpair;
|
std::pair<float,float> floatpair;
|
||||||
|
|
||||||
//channel
|
//channel
|
||||||
if(tch.subChunkPtr("channel") == nullptr || tch["channel"] == "*")
|
if(tch.subChunkPtr("channel") == nullptr || tch["channel"].strval()=="*")
|
||||||
channel=-1;
|
channel=-1;
|
||||||
else
|
else
|
||||||
channel=std::stoi(tch["channel"]);
|
channel=stoi(tch["channel"].strval());
|
||||||
|
|
||||||
//shell
|
//shell
|
||||||
shell=tch["shell"];
|
shell=tch["shell"].strval();
|
||||||
|
|
||||||
//type
|
//type
|
||||||
if(tstr == "note") //type note
|
if(tstr == "note") //type note
|
||||||
|
|
@ -177,11 +182,13 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
uint8_t id_high=127;
|
uint8_t id_high=127;
|
||||||
uint8_t low=1;
|
uint8_t low=1;
|
||||||
uint8_t high=127;
|
uint8_t high=127;
|
||||||
|
std::string tt;
|
||||||
|
|
||||||
//id
|
//id
|
||||||
intpair=importRange(tch, "id", id_low, id_high);
|
intpair=importRange(tch, "id", id_low, id_high);
|
||||||
id_low=intpair.first;
|
id_low=intpair.first;
|
||||||
id_high=intpair.second;
|
id_high=intpair.second;
|
||||||
|
// id=stoi(tch["id"].strval());
|
||||||
|
|
||||||
//trigger
|
//trigger
|
||||||
intpair = importRange(tch, "trigger", low, high);
|
intpair = importRange(tch, "trigger", low, high);
|
||||||
|
|
@ -192,6 +199,7 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
{
|
{
|
||||||
this->noteCommands[i].push_back(NoteCommand(channel,low,high,shell));
|
this->noteCommands[i].push_back(NoteCommand(channel,low,high,shell));
|
||||||
}
|
}
|
||||||
|
this->nb_command++;
|
||||||
}
|
}
|
||||||
else if(tstr == "controller") //type controller
|
else if(tstr == "controller") //type controller
|
||||||
{
|
{
|
||||||
|
|
@ -225,6 +233,7 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
{
|
{
|
||||||
this->ctrlCommands[i].push_back(ControllerCommand(channel,min,max,mapMin,mapMax,floating,shell));
|
this->ctrlCommands[i].push_back(ControllerCommand(channel,min,max,mapMin,mapMax,floating,shell));
|
||||||
}
|
}
|
||||||
|
this->nb_command++;
|
||||||
}
|
}
|
||||||
else if(tstr == "pitch") //type pitch bend
|
else if(tstr == "pitch") //type pitch bend
|
||||||
{
|
{
|
||||||
|
|
@ -248,6 +257,7 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
floating = importBool(tch, "float", floating);
|
floating = importBool(tch, "float", floating);
|
||||||
|
|
||||||
this->pitchCommands.push_back(PitchCommand(channel,min,max,mapMin,mapMax,floating,shell));
|
this->pitchCommands.push_back(PitchCommand(channel,min,max,mapMin,mapMax,floating,shell));
|
||||||
|
this->nb_command++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -255,7 +265,6 @@ bool Device::import_chunk(const ztd::chunkdat& ch)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->nb_command++;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +295,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::shr, command).detach();
|
std::thread(sh, command).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -294,7 +303,7 @@ void Device::run_signal(char* buff)
|
||||||
int t;
|
int t;
|
||||||
char type;
|
char type;
|
||||||
int8_t channel;
|
int8_t channel;
|
||||||
int8_t ctid=-1;
|
int ctid;
|
||||||
int16_t value;
|
int16_t value;
|
||||||
char* pos=NULL;
|
char* pos=NULL;
|
||||||
bool note_off=false;
|
bool note_off=false;
|
||||||
|
|
@ -313,7 +322,7 @@ void Device::run_signal(char* buff)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// throw std::runtime_error("Unknown MIDI signal:\n" + std::string(buff));
|
// throw std::runtime_error("Unknown MIDI signal:\n" + std::string(buff));
|
||||||
std::cerr << "Unsupported signal, ignoring\n" ;
|
printf("Unsupported signal, ignoring\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -363,7 +372,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::shr, command).detach();
|
std::thread(sh, command).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -390,7 +399,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::shr, command).detach();
|
std::thread(sh, command).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -416,7 +425,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::shr, command).detach();
|
std::thread(sh, command).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // if type
|
} // if type
|
||||||
|
|
@ -438,7 +447,7 @@ void Device::loop(Device* dev)
|
||||||
|
|
||||||
for( auto it : dev->connectCommands )
|
for( auto it : dev->connectCommands )
|
||||||
{
|
{
|
||||||
std::thread(ztd::shr, dequote(it.shell)).detach();
|
std::thread(sh, dequote(it.shell)).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
while (getline(&buff, &buff_size, stream) > 0)
|
while (getline(&buff, &buff_size, stream) > 0)
|
||||||
|
|
@ -448,7 +457,7 @@ void Device::loop(Device* dev)
|
||||||
|
|
||||||
for( auto it : dev->disconnectCommands )
|
for( auto it : dev->disconnectCommands )
|
||||||
{
|
{
|
||||||
std::thread(ztd::shr, dequote(it.shell)).detach();
|
std::thread(sh, dequote(it.shell)).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
log("Device '" + dev->name + "' disconnected\n");
|
log("Device '" + dev->name + "' disconnected\n");
|
||||||
|
|
@ -457,12 +466,3 @@ void Device::loop(Device* dev)
|
||||||
dev->thread_pid=-1;
|
dev->thread_pid=-1;
|
||||||
free(buff);
|
free(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clean_devices()
|
|
||||||
{
|
|
||||||
for(auto it : device_list)
|
|
||||||
{
|
|
||||||
delete it;
|
|
||||||
}
|
|
||||||
device_list.clear();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -71,9 +71,8 @@ ztd::chunkdat mimtochk_commands(const std::string& mim)
|
||||||
return chk;
|
return chk;
|
||||||
}
|
}
|
||||||
|
|
||||||
ztd::chunkdat mimtochk(std::string mim)
|
ztd::chunkdat mimtochk(const std::string& mim)
|
||||||
{
|
{
|
||||||
mim = ztd::filedat::removeComments(mim);
|
|
||||||
ztd::chunkdat chk;
|
ztd::chunkdat chk;
|
||||||
unsigned int i=0,j=0;
|
unsigned int i=0,j=0;
|
||||||
_find_next(mim,i, "Device ");
|
_find_next(mim,i, "Device ");
|
||||||
|
|
@ -98,29 +97,6 @@ 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;
|
||||||
|
|
|
||||||
267
src/main.cpp
267
src/main.cpp
|
|
@ -14,7 +14,7 @@
|
||||||
#include <ztd/options.hpp>
|
#include <ztd/options.hpp>
|
||||||
#include <ztd/shell.hpp>
|
#include <ztd/shell.hpp>
|
||||||
|
|
||||||
#define VERSION_STRING "v1.3.1a"
|
#define VERSION_STRING "v1.2"
|
||||||
|
|
||||||
ztd::option_set options;
|
ztd::option_set options;
|
||||||
|
|
||||||
|
|
@ -23,6 +23,7 @@ void help()
|
||||||
printf("zmidimap [options] <file>\n\nOptions:\n");
|
printf("zmidimap [options] <file>\n\nOptions:\n");
|
||||||
options.print_help(4, 25);
|
options.print_help(4, 25);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
printf("If piped, the map file will be read from standard input\n");
|
||||||
printf("See --mim-format --zfd-format --command-tags --shell-format options for details on map file format\n");
|
printf("See --mim-format --zfd-format --command-tags --shell-format options for details on map file format\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -58,7 +59,8 @@ void cleanup()
|
||||||
|
|
||||||
void stop(int ret)
|
void stop(int ret)
|
||||||
{
|
{
|
||||||
kill_all();
|
if(announce_thread_pid>0)
|
||||||
|
kill(announce_thread_pid, SIGINT);
|
||||||
exit(ret);
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -67,104 +69,37 @@ void inthandler(int dummy)
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_filedat(ztd::filedat& file, bool from_stdin, std::string const& path)
|
|
||||||
{
|
|
||||||
if(from_stdin)
|
|
||||||
{
|
|
||||||
log("Loading map from stdin\n");
|
|
||||||
file.setFilePath(path);
|
|
||||||
std::string str=file_strimport(path);
|
|
||||||
|
|
||||||
if(options["zfd"])
|
|
||||||
{
|
|
||||||
file.data() = str;
|
|
||||||
}
|
|
||||||
else if(options["mim"])
|
|
||||||
{
|
|
||||||
file.data() = mimtochk(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(is_mim(str))
|
|
||||||
{
|
|
||||||
file.data() = mimtochk(str);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file.data() = str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file.setFilePath(path);
|
|
||||||
log("Loading map file '" + path + "'\n");
|
|
||||||
if(options["zfd"])
|
|
||||||
{
|
|
||||||
file.import_file();
|
|
||||||
}
|
|
||||||
else if(options["mim"])
|
|
||||||
{
|
|
||||||
file.data() = mimtochk(file_strimport(path));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string filestr=file_strimport(path);
|
|
||||||
if(is_mim(filestr))
|
|
||||||
{
|
|
||||||
file.data() = mimtochk(filestr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
file.import_file();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void load_commands(ztd::chunkdat const& data)
|
|
||||||
{
|
|
||||||
clean_devices();
|
|
||||||
for(int i=0 ; i<data.listSize() ; i++)
|
|
||||||
{
|
|
||||||
Device *newDevice = new Device;
|
|
||||||
newDevice->import_chunk(data[i]);
|
|
||||||
device_list.push_back(newDevice);
|
|
||||||
log("Loaded "+std::to_string(newDevice->nb_command)+" commands for device '"+newDevice->name+"'\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
signal(SIGINT, inthandler);
|
signal(SIGINT, inthandler);
|
||||||
signal(SIGCHLD, SIG_IGN); //not expecting returns from child processes
|
signal(SIGCHLD, SIG_IGN); //not expecting returns from child processes
|
||||||
|
|
||||||
bool autoreload=true;
|
bool piped=false;
|
||||||
bool from_stdin=false;
|
if (!isatty(fileno(stdin)))
|
||||||
|
piped = true;
|
||||||
|
|
||||||
options.add(
|
options.add(ztd::option("\r [Help]"));
|
||||||
ztd::option("\r [Help]"),
|
options.add(ztd::option('h',"help", false, "Display this help message"));
|
||||||
ztd::option('h',"help", false, "Display this help message"),
|
options.add(ztd::option('v',"version", false, "Display version"));
|
||||||
ztd::option('v',"version", false, "Display version"),
|
options.add(ztd::option("mim-format", false, "Display mim file format help"));
|
||||||
ztd::option("mim-format", false, "Display mim file format help"),
|
options.add(ztd::option("zfd-format", false, "Display zfd file format help"));
|
||||||
ztd::option("zfd-format", false, "Display zfd file format help"),
|
options.add(ztd::option("command-tags", false, "Display for command tag help"));
|
||||||
ztd::option("command-tags", false, "Display for command tag help"),
|
options.add(ztd::option("shell-format", false, "Display for shell format help"));
|
||||||
ztd::option("shell-format", false, "Display for shell format help"),
|
|
||||||
ztd::option("\r [Format]"),
|
options.add(ztd::option("\r [Format]"));
|
||||||
ztd::option("no-log", false, "Disable console logging"),
|
options.add(ztd::option("no-log", false, "Disable console logging"));
|
||||||
ztd::option("\r [Devices]"),
|
|
||||||
ztd::option('l',"list", false, "List detected devices"),
|
options.add(ztd::option("\r [Devices]"));
|
||||||
ztd::option('L',"full-list", false, "Print whole device list details"),
|
options.add(ztd::option('l',"list", false, "List detected devices"));
|
||||||
ztd::option('p',"port", true, "Connect to device and output to console", "device"),
|
options.add(ztd::option('L',"full-list", false, "Print whole device list details"));
|
||||||
ztd::option("\r [Map file]"),
|
options.add(ztd::option('p',"port", true, "Connect to device and output to console", "device"));
|
||||||
ztd::option('m',"mim", false, "Read file in mim format"),
|
options.add(ztd::option("\r [Map file]"));
|
||||||
ztd::option('z',"zfd", false, "Read file in zfd format"),
|
options.add(ztd::option('m',"mim", false, "Read file in mim format"));
|
||||||
ztd::option('o',"output", true, "Output the resulting map to file", "file"),
|
options.add(ztd::option('z',"zfd", false, "Read file in zfd format"));
|
||||||
ztd::option("out-zfd", false, "Output in zfd format"),
|
options.add(ztd::option('o',"output", true, "Output the resulting zfd map to file. - for stdout", "file"));
|
||||||
ztd::option("aligner", true, "String to use for aligning output map format. Default \\t", "string"),
|
options.add(ztd::option("aligner", true, "String to use for aligning output map format. Default \\t", "string"));
|
||||||
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
|
||||||
|
|
@ -174,156 +109,148 @@ int main(int argc, char* argv[])
|
||||||
catch(ztd::option_error& err)
|
catch(ztd::option_error& err)
|
||||||
{
|
{
|
||||||
printf("%s\n", err.what());
|
printf("%s\n", err.what());
|
||||||
if(err.type() == ztd::option_error::unknown_option)
|
|
||||||
help();
|
|
||||||
stop(1);
|
stop(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ztd::option* op=nullptr;
|
||||||
//exit options
|
//exit options
|
||||||
if( options['h'] )
|
if( options.find('h')->activated )
|
||||||
{
|
{
|
||||||
help();
|
help();
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options['v'] )
|
if( options.find('v')->activated )
|
||||||
{
|
{
|
||||||
version();
|
version();
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options["mim-format"] )
|
if( options.find("mim-format")->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", MIM_FORMAT);
|
printf("%s\n", MIM_FORMAT);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options["zfd-format"] )
|
if( options.find("zfd-format")->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", ZFD_FORMAT);
|
printf("%s\n", ZFD_FORMAT);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options["command-tags"] )
|
if( options.find("command-tags")->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", COMMAND_TAGS);
|
printf("%s\n", COMMAND_TAGS);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options["shell-format"] )
|
if( options.find("shell-format")->activated )
|
||||||
{
|
{
|
||||||
printf("%s\n", SHELL_FORMAT);
|
printf("%s\n", SHELL_FORMAT);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options['L'] )
|
if( options.find('L')->activated )
|
||||||
{
|
{
|
||||||
ztd::shr("aseqdump -l");
|
sh("aseqdump -l");
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
if( options['l'] )
|
if( options.find('l')->activated )
|
||||||
{
|
{
|
||||||
ztd::shr(LIST_COMMAND);
|
sh(LIST_COMMAND);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( options['p'] )
|
op = options.find('p');
|
||||||
|
if( op->activated )
|
||||||
{
|
{
|
||||||
option_p(options['p']);
|
option_p(op->argument);
|
||||||
stop(0);
|
stop(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options['o'])
|
if (options.find('o')->activated)
|
||||||
{
|
{
|
||||||
log_on=false;
|
log_on=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//behavioral options
|
//behavioral options
|
||||||
if( options["no-reload"] )
|
if( options.find("no-log")->activated )
|
||||||
{
|
|
||||||
autoreload=false;
|
|
||||||
}
|
|
||||||
if( options["no-log"] )
|
|
||||||
{
|
{
|
||||||
log_on=false;
|
log_on=false;
|
||||||
}
|
}
|
||||||
std::string aligner="\t";
|
std::string aligner="\t";
|
||||||
if(options["aligner"])
|
if(options.find("aligner")->activated)
|
||||||
{
|
{
|
||||||
aligner=options["aligner"].argument;
|
aligner=options.find("aligner")->argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
//no argument: display help
|
//no argument: display help
|
||||||
ztd::filedat file;
|
ztd::filedat file;
|
||||||
std::string filepath;
|
bool no_arg=false;
|
||||||
if (arg.size() <= 0 || arg[0] == "")
|
if (arg.size() <= 0 || arg[0] == "")
|
||||||
{
|
{
|
||||||
help();
|
no_arg=true;
|
||||||
stop(0);
|
if(!piped)
|
||||||
|
{
|
||||||
|
help();
|
||||||
|
stop(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
filepath=arg[0];
|
file.setFilePath(arg[0]);
|
||||||
}
|
|
||||||
if(filepath == "-")
|
|
||||||
{
|
|
||||||
filepath = "/dev/stdin";
|
|
||||||
from_stdin = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//main processing
|
//main processing
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//load
|
if(no_arg)
|
||||||
load_filedat(file, from_stdin, filepath);
|
|
||||||
//output
|
|
||||||
if(options['o'])
|
|
||||||
{
|
{
|
||||||
std::string ret;
|
log("Loading map from stdin\n");
|
||||||
if(options["out-zfd"])
|
file.import_stdin();
|
||||||
ret=file.data().str(0, aligner);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log("Loading map file '" + arg[0] + "'\n");
|
||||||
|
if(options.find("zfd")->activated)
|
||||||
|
{
|
||||||
|
file.import_file();
|
||||||
|
}
|
||||||
|
else if(options.find("mim")->activated)
|
||||||
|
{
|
||||||
|
file.data() = mimtochk(file_strimport(arg[0]));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ret=chktomim(file.data(), aligner);
|
{
|
||||||
if(options['o'].argument == "-") {
|
std::string filestr=file_strimport(arg[0]);
|
||||||
std::cout << ret << std::endl;
|
if(is_mim(filestr))
|
||||||
|
{
|
||||||
|
file.data() = mimtochk(filestr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
file.import_file();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(options.find('o')->activated)
|
||||||
|
{
|
||||||
|
if(options.find('o')->argument == "-") {
|
||||||
|
std::cout << file.strval(aligner) << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::ofstream output(options['o']);
|
file.setFilePath(options.find('o')->argument);
|
||||||
if(!output)
|
file.export_file();
|
||||||
{
|
|
||||||
std::cerr << "Cannot write to file '" + options['o'].argument + "'\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
output << ret << std::endl ;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
//create commands
|
//create commands
|
||||||
load_commands(file.data());
|
for(int i=0 ; i<file.data().listSize() ; i++)
|
||||||
|
{
|
||||||
|
Device *newDevice = new Device;
|
||||||
|
newDevice->import_chunk(file[i]);
|
||||||
|
device_list.push_back(newDevice);
|
||||||
|
log("Loaded "+std::to_string(newDevice->nb_command)+" commands for device '"+newDevice->name+"'\n");
|
||||||
|
}
|
||||||
|
|
||||||
//main loop
|
//main loop
|
||||||
log("Starting scan for devices\n");
|
log("Starting scan for devices\n");
|
||||||
if(autoreload)
|
announce_loop();
|
||||||
std::thread(filetime_loop, filepath).detach(); // start the killer thread
|
|
||||||
announce_loop(); // loop until killed
|
|
||||||
ztd::chunkdat bak_data = file.data();
|
|
||||||
while(autoreload)
|
|
||||||
{
|
|
||||||
log("Reloading file\n");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
load_filedat(file, from_stdin, filepath);
|
|
||||||
load_commands(file.data());
|
|
||||||
bak_data = file.data();
|
|
||||||
}
|
|
||||||
catch (ztd::format_error& e)
|
|
||||||
{
|
|
||||||
ztd::printFormatException(e);
|
|
||||||
log("Reloading old config\n");
|
|
||||||
load_commands(bak_data);
|
|
||||||
}
|
|
||||||
catch (std::exception& e)
|
|
||||||
{
|
|
||||||
std::cerr << "Exception: " << e.what() << std::endl;
|
|
||||||
log("Reloading old config\n");
|
|
||||||
load_commands(bak_data);
|
|
||||||
}
|
|
||||||
announce_loop(); // loop until killed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (ztd::format_error& e)
|
catch (ztd::format_error& e)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
@ -17,17 +13,6 @@
|
||||||
|
|
||||||
int announce_thread_pid = 0;
|
int announce_thread_pid = 0;
|
||||||
|
|
||||||
void kill_all()
|
|
||||||
{
|
|
||||||
if(announce_thread_pid>0)
|
|
||||||
kill(announce_thread_pid, SIGINT);
|
|
||||||
for(auto it : device_list)
|
|
||||||
{
|
|
||||||
if(it->thread_pid>0)
|
|
||||||
kill(it->thread_pid, SIGINT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void device_check()
|
void device_check()
|
||||||
{
|
{
|
||||||
char* buff = NULL;
|
char* buff = NULL;
|
||||||
|
|
@ -101,20 +86,3 @@ void announce_loop()
|
||||||
if(buff != NULL)
|
if(buff != NULL)
|
||||||
free(buff);
|
free(buff);
|
||||||
}
|
}
|
||||||
|
|
||||||
void filetime_loop(std::string const& filepath)
|
|
||||||
{
|
|
||||||
struct stat attrib;
|
|
||||||
stat(filepath.c_str(), &attrib);
|
|
||||||
time_t last_time=attrib.st_ctime;
|
|
||||||
while(true)
|
|
||||||
{
|
|
||||||
stat(filepath.c_str(), &attrib);
|
|
||||||
if(attrib.st_ctime > last_time)
|
|
||||||
{
|
|
||||||
kill_all();
|
|
||||||
last_time = attrib.st_ctime;
|
|
||||||
}
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue