mirror of
https://git.sr.ht/~thestr4ng3r/chiaki
synced 2025-08-14 02:36:51 -07:00
Integrate CLI in GUI
This commit is contained in:
parent
c7e4fd778b
commit
3148f1ea93
7 changed files with 136 additions and 148 deletions
|
@ -19,12 +19,13 @@
|
||||||
#define CHIAKI_CHIAKI_CLI_H
|
#define CHIAKI_CHIAKI_CLI_H
|
||||||
|
|
||||||
#include <chiaki/common.h>
|
#include <chiaki/common.h>
|
||||||
|
#include <chiaki/log.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CHIAKI_EXPORT int chiaki_cli_cmd_discover(int argc, char *argv[]);
|
CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[]);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,20 +17,26 @@
|
||||||
|
|
||||||
#include <chiaki-cli.h>
|
#include <chiaki-cli.h>
|
||||||
|
|
||||||
|
#include <chiaki/discovery.h>
|
||||||
|
|
||||||
#include <argp.h>
|
#include <argp.h>
|
||||||
|
|
||||||
|
#include <netdb.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static char doc[] = "Send a PS4 discovery request.";
|
static char doc[] = "Send a PS4 discovery request.";
|
||||||
|
|
||||||
|
#define ARG_KEY_HOST 'h'
|
||||||
|
|
||||||
static struct argp_option options[] = {
|
static struct argp_option options[] = {
|
||||||
{ "ip", 'i', "IP", 0, "IP to send discovery request to", 0 },
|
{ "host", ARG_KEY_HOST, "Host", 0, "Host to send discovery request to", 0 },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct arguments
|
typedef struct arguments
|
||||||
{
|
{
|
||||||
char *ip;
|
const char *host;
|
||||||
} Arguments;
|
} Arguments;
|
||||||
|
|
||||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||||
|
@ -39,8 +45,8 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||||
|
|
||||||
switch(key)
|
switch(key)
|
||||||
{
|
{
|
||||||
case 'i':
|
case ARG_KEY_HOST:
|
||||||
arguments->ip = arg;
|
arguments->host = arg;
|
||||||
break;
|
break;
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
argp_usage(state);
|
argp_usage(state);
|
||||||
|
@ -54,21 +60,77 @@ static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||||
|
|
||||||
static struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
|
static struct argp argp = { options, parse_opt, 0, doc, 0, 0, 0 };
|
||||||
|
|
||||||
CHIAKI_EXPORT int chiaki_cli_cmd_discover(int argc, char *argv[])
|
CHIAKI_EXPORT int chiaki_cli_cmd_discover(ChiakiLog *log, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
Arguments arguments = { 0 };
|
Arguments arguments = { 0 };
|
||||||
error_t r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
|
error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
|
||||||
if(r != 0)
|
if(argp_r != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if(!arguments.ip)
|
if(!arguments.host)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "ip for discovery is not set.\n");
|
fprintf(stderr, "No host specified, see --help.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO
|
ChiakiDiscovery discovery;
|
||||||
printf("run discovery\n");
|
ChiakiErrorCode err = chiaki_discovery_init(&discovery, log, AF_INET); // TODO: IPv6
|
||||||
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
|
{
|
||||||
|
CHIAKI_LOGE(log, "Discovery init failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChiakiDiscoveryThread thread;
|
||||||
|
err = chiaki_discovery_thread_start(&thread, &discovery);
|
||||||
|
if(err != CHIAKI_ERR_SUCCESS)
|
||||||
|
{
|
||||||
|
CHIAKI_LOGE(log, "Discovery thread init failed");
|
||||||
|
chiaki_discovery_fini(&discovery);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct addrinfo *host_addrinfos;
|
||||||
|
int r = getaddrinfo(arguments.host, NULL, NULL, &host_addrinfos);
|
||||||
|
if(r != 0)
|
||||||
|
{
|
||||||
|
CHIAKI_LOGE(log, "getaddrinfo failed");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr *host_addr = NULL;
|
||||||
|
socklen_t host_addr_len = 0;
|
||||||
|
for(struct addrinfo *ai=host_addrinfos; ai; ai=ai->ai_next)
|
||||||
|
{
|
||||||
|
if(ai->ai_protocol != IPPROTO_UDP)
|
||||||
|
continue;
|
||||||
|
if(ai->ai_family != AF_INET) // TODO: IPv6
|
||||||
|
continue;
|
||||||
|
|
||||||
|
host_addr_len = ai->ai_addrlen;
|
||||||
|
host_addr = (struct sockaddr *)malloc(host_addr_len);
|
||||||
|
if(!host_addr)
|
||||||
|
break;
|
||||||
|
memcpy(host_addr, ai->ai_addr, host_addr_len);
|
||||||
|
}
|
||||||
|
freeaddrinfo(host_addrinfos);
|
||||||
|
|
||||||
|
if(!host_addr)
|
||||||
|
{
|
||||||
|
CHIAKI_LOGE(log, "Failed to get addr for hostname");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT); // TODO: IPv6
|
||||||
|
|
||||||
|
ChiakiDiscoveryPacket packet;
|
||||||
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
|
||||||
|
|
||||||
|
chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -29,11 +29,19 @@ static const char doc[] =
|
||||||
"Supported commands are:\n"
|
"Supported commands are:\n"
|
||||||
" discover Discover Consoles.\n";
|
" discover Discover Consoles.\n";
|
||||||
|
|
||||||
|
#define ARG_KEY_VERBOSE 'v'
|
||||||
|
|
||||||
static struct argp_option options[] = {
|
static struct argp_option options[] = {
|
||||||
|
{ "verbose", ARG_KEY_VERBOSE, NULL, 0, "Verbose Logging", 0 },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
static int call_subcmd(struct argp_state *state, const char *name, int (*subcmd)(int argc, char *argv[]))
|
typedef struct context
|
||||||
|
{
|
||||||
|
ChiakiLog log;
|
||||||
|
} Context;
|
||||||
|
|
||||||
|
static int call_subcmd(struct argp_state *state, const char *name, int (*subcmd)(ChiakiLog *log, int argc, char *argv[]))
|
||||||
{
|
{
|
||||||
if(state->next < 1 || state->argc < state->next)
|
if(state->next < 1 || state->argc < state->next)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -47,7 +55,7 @@ static int call_subcmd(struct argp_state *state, const char *name, int (*subcmd)
|
||||||
return 1;
|
return 1;
|
||||||
snprintf(argv[0], l, "%s %s", state->name, name);
|
snprintf(argv[0], l, "%s %s", state->name, name);
|
||||||
|
|
||||||
int r = subcmd(argc, argv);
|
int r = subcmd(state->input, argc, argv);
|
||||||
|
|
||||||
free(argv[0]);
|
free(argv[0]);
|
||||||
return r;
|
return r;
|
||||||
|
@ -55,8 +63,13 @@ static int call_subcmd(struct argp_state *state, const char *name, int (*subcmd)
|
||||||
|
|
||||||
static int parse_opt(int key, char *arg, struct argp_state *state)
|
static int parse_opt(int key, char *arg, struct argp_state *state)
|
||||||
{
|
{
|
||||||
|
Context *ctx = state->input;
|
||||||
|
|
||||||
switch(key)
|
switch(key)
|
||||||
{
|
{
|
||||||
|
case ARG_KEY_VERBOSE:
|
||||||
|
ctx->log.level_mask = CHIAKI_LOG_ALL;
|
||||||
|
break;
|
||||||
case ARGP_KEY_ARG:
|
case ARGP_KEY_ARG:
|
||||||
if(strcmp(arg, "discover") == 0)
|
if(strcmp(arg, "discover") == 0)
|
||||||
exit(call_subcmd(state, "discover", chiaki_cli_cmd_discover));
|
exit(call_subcmd(state, "discover", chiaki_cli_cmd_discover));
|
||||||
|
@ -74,7 +87,11 @@ static struct argp argp = { options, parse_opt, "<cmd> [CMD-ARGS...]", doc, 0, 0
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, NULL);
|
Context ctx;
|
||||||
|
chiaki_log_init(&ctx.log, CHIAKI_LOG_ALL & ~CHIAKI_LOG_VERBOSE, chiaki_log_cb_print, NULL);
|
||||||
|
|
||||||
|
argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &ctx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@ add_executable(chiaki
|
||||||
src/streamwindow.cpp
|
src/streamwindow.cpp
|
||||||
include/videodecoder.h
|
include/videodecoder.h
|
||||||
src/videodecoder.cpp
|
src/videodecoder.cpp
|
||||||
include/discoverycmd.h
|
|
||||||
src/discoverycmd.cpp
|
|
||||||
include/mainwindow.h
|
include/mainwindow.h
|
||||||
src/mainwindow.cpp
|
src/mainwindow.cpp
|
||||||
include/dynamicgridwidget.h
|
include/dynamicgridwidget.h
|
||||||
|
@ -39,7 +37,7 @@ add_executable(chiaki
|
||||||
src/avopenglframeuploader.cpp)
|
src/avopenglframeuploader.cpp)
|
||||||
target_include_directories(chiaki PRIVATE include)
|
target_include_directories(chiaki PRIVATE include)
|
||||||
|
|
||||||
target_link_libraries(chiaki chiaki-lib)
|
target_link_libraries(chiaki chiaki-lib chiaki-cli-lib)
|
||||||
target_link_libraries(chiaki FFMPEG::avcodec)
|
target_link_libraries(chiaki FFMPEG::avcodec)
|
||||||
target_link_libraries(chiaki Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Multimedia Qt5::OpenGL)
|
target_link_libraries(chiaki Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Multimedia Qt5::OpenGL)
|
||||||
if(CHIAKI_GUI_ENABLE_QT_GAMEPAD)
|
if(CHIAKI_GUI_ENABLE_QT_GAMEPAD)
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Chiaki.
|
|
||||||
*
|
|
||||||
* Chiaki is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Chiaki is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHIAKI_DISCOVERYCMD_H
|
|
||||||
#define CHIAKI_DISCOVERYCMD_H
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
int RunDiscoveryCmd(const QString &host);
|
|
||||||
|
|
||||||
#endif //CHIAKI_DISCOVERYCMD_H
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of Chiaki.
|
|
||||||
*
|
|
||||||
* Chiaki is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Chiaki is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Chiaki. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <discoverycmd.h>
|
|
||||||
|
|
||||||
#include <chiaki/log.h>
|
|
||||||
#include <chiaki/discovery.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
|
|
||||||
|
|
||||||
int RunDiscoveryCmd(const QString &host)
|
|
||||||
{
|
|
||||||
ChiakiLog log;
|
|
||||||
chiaki_log_init(&log, CHIAKI_LOG_ALL, chiaki_log_cb_print, NULL);
|
|
||||||
|
|
||||||
ChiakiDiscovery discovery;
|
|
||||||
ChiakiErrorCode err = chiaki_discovery_init(&discovery, &log, AF_INET); // TODO: IPv6
|
|
||||||
if(err != CHIAKI_ERR_SUCCESS)
|
|
||||||
{
|
|
||||||
CHIAKI_LOGE(&log, "Discovery init failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChiakiDiscoveryThread thread;
|
|
||||||
err = chiaki_discovery_thread_start(&thread, &discovery);
|
|
||||||
if(err != CHIAKI_ERR_SUCCESS)
|
|
||||||
{
|
|
||||||
CHIAKI_LOGE(&log, "Discovery thread init failed");
|
|
||||||
chiaki_discovery_fini(&discovery);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct addrinfo *host_addrinfos;
|
|
||||||
int r = getaddrinfo(host.toUtf8().constData(), NULL, NULL, &host_addrinfos);
|
|
||||||
if(r != 0)
|
|
||||||
{
|
|
||||||
CHIAKI_LOGE(&log, "getaddrinfo failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sockaddr *host_addr = nullptr;
|
|
||||||
socklen_t host_addr_len = 0;
|
|
||||||
for(struct addrinfo *ai=host_addrinfos; ai; ai=ai->ai_next)
|
|
||||||
{
|
|
||||||
if(ai->ai_protocol != IPPROTO_UDP)
|
|
||||||
continue;
|
|
||||||
if(ai->ai_family != AF_INET) // TODO: IPv6
|
|
||||||
continue;
|
|
||||||
|
|
||||||
host_addr_len = ai->ai_addrlen;
|
|
||||||
host_addr = (struct sockaddr *)malloc(host_addr_len);
|
|
||||||
if(!host_addr)
|
|
||||||
break;
|
|
||||||
memcpy(host_addr, ai->ai_addr, host_addr_len);
|
|
||||||
}
|
|
||||||
freeaddrinfo(host_addrinfos);
|
|
||||||
|
|
||||||
if(!host_addr)
|
|
||||||
CHIAKI_LOGE(&log, "Failed to get addr for hostname");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
((struct sockaddr_in *)host_addr)->sin_port = htons(CHIAKI_DISCOVERY_PORT); // TODO: IPv6
|
|
||||||
|
|
||||||
ChiakiDiscoveryPacket packet;
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
|
||||||
packet.cmd = CHIAKI_DISCOVERY_CMD_SRCH;
|
|
||||||
|
|
||||||
chiaki_discovery_send(&discovery, &packet, host_addr, host_addr_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
while(1)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,10 +1,11 @@
|
||||||
|
|
||||||
#include <streamwindow.h>
|
#include <streamwindow.h>
|
||||||
#include <videodecoder.h>
|
#include <videodecoder.h>
|
||||||
#include <discoverycmd.h>
|
|
||||||
#include <mainwindow.h>
|
#include <mainwindow.h>
|
||||||
#include <streamsession.h>
|
#include <streamsession.h>
|
||||||
|
|
||||||
|
#include <chiaki-cli.h>
|
||||||
|
|
||||||
#include <chiaki/session.h>
|
#include <chiaki/session.h>
|
||||||
#include <chiaki/base64.h>
|
#include <chiaki/base64.h>
|
||||||
|
|
||||||
|
@ -15,7 +16,16 @@
|
||||||
#include <QAudioOutput>
|
#include <QAudioOutput>
|
||||||
#include <QAudioFormat>
|
#include <QAudioFormat>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
struct CLICommand
|
||||||
|
{
|
||||||
|
int (*cmd)(ChiakiLog *log, int argc, char *argv[]);
|
||||||
|
};
|
||||||
|
|
||||||
|
static const QMap<QString, CLICommand> cli_commands = {
|
||||||
|
{ "discover", { chiaki_cli_cmd_discover } }
|
||||||
|
};
|
||||||
|
|
||||||
int RunStream(QApplication &app, const StreamSessionConnectInfo &connect_info);
|
int RunStream(QApplication &app, const StreamSessionConnectInfo &connect_info);
|
||||||
int RunMain(QApplication &app);
|
int RunMain(QApplication &app);
|
||||||
|
@ -35,10 +45,15 @@ int main(int argc, char *argv[])
|
||||||
QApplication::setApplicationName("Chiaki");
|
QApplication::setApplicationName("Chiaki");
|
||||||
|
|
||||||
QCommandLineParser parser;
|
QCommandLineParser parser;
|
||||||
|
parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
||||||
parser.addPositionalArgument("command", "stream or discover");
|
QStringList cmds;
|
||||||
parser.addPositionalArgument("host", "Address to connect to");
|
cmds.append("stream");
|
||||||
|
cmds.append(cli_commands.keys());
|
||||||
|
|
||||||
|
parser.addPositionalArgument("command", cmds.join(", "));
|
||||||
|
parser.addPositionalArgument("host", "Address to connect to (when using the stream command)");
|
||||||
|
|
||||||
QCommandLineOption regist_key_option("registkey", "", "registkey");
|
QCommandLineOption regist_key_option("registkey", "", "registkey");
|
||||||
parser.addOption(regist_key_option);
|
parser.addOption(regist_key_option);
|
||||||
|
@ -62,13 +77,13 @@ int main(int argc, char *argv[])
|
||||||
if(args.length() == 0)
|
if(args.length() == 0)
|
||||||
return RunMain(app);
|
return RunMain(app);
|
||||||
|
|
||||||
if(args.length() < 2)
|
|
||||||
parser.showHelp(1);
|
|
||||||
|
|
||||||
QString host = args[1];
|
|
||||||
|
|
||||||
if(args[0] == "stream")
|
if(args[0] == "stream")
|
||||||
{
|
{
|
||||||
|
if(args.length() < 2)
|
||||||
|
parser.showHelp(1);
|
||||||
|
|
||||||
|
QString host = args[1];
|
||||||
|
|
||||||
StreamSessionConnectInfo connect_info;
|
StreamSessionConnectInfo connect_info;
|
||||||
|
|
||||||
connect_info.log_level_mask = CHIAKI_LOG_ALL & ~CHIAKI_LOG_VERBOSE;
|
connect_info.log_level_mask = CHIAKI_LOG_ALL & ~CHIAKI_LOG_VERBOSE;
|
||||||
|
@ -87,11 +102,25 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
if(connect_info.registkey.isEmpty() || connect_info.ostype.isEmpty() || connect_info.auth.isEmpty() || connect_info.morning.isEmpty() || connect_info.did.isEmpty())
|
if(connect_info.registkey.isEmpty() || connect_info.ostype.isEmpty() || connect_info.auth.isEmpty() || connect_info.morning.isEmpty() || connect_info.did.isEmpty())
|
||||||
parser.showHelp(1);
|
parser.showHelp(1);
|
||||||
|
|
||||||
return RunStream(app, connect_info);
|
return RunStream(app, connect_info);
|
||||||
}
|
}
|
||||||
else if(args[0] == "discover")
|
else if(cli_commands.contains(args[0]))
|
||||||
{
|
{
|
||||||
return RunDiscoveryCmd(args[1]);
|
ChiakiLog log;
|
||||||
|
// TODO: add verbose arg
|
||||||
|
chiaki_log_init(&log, CHIAKI_LOG_ALL & ~CHIAKI_LOG_VERBOSE, chiaki_log_cb_print, nullptr);
|
||||||
|
|
||||||
|
const auto &cmd = cli_commands[args[0]];
|
||||||
|
int sub_argc = args.count();
|
||||||
|
QVector<QByteArray> sub_argv_b(sub_argc);
|
||||||
|
QVector<char *> sub_argv(sub_argc);
|
||||||
|
for(size_t i=0; i<sub_argc; i++)
|
||||||
|
{
|
||||||
|
sub_argv_b[i] = args[i].toLocal8Bit();
|
||||||
|
sub_argv[i] = sub_argv_b[i].data();
|
||||||
|
}
|
||||||
|
return cmd.cmd(&log, sub_argc, sub_argv.data());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue