Integrate CLI in GUI

This commit is contained in:
Florian Märkl 2019-08-11 20:19:55 +02:00
commit 3148f1ea93
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
7 changed files with 136 additions and 148 deletions

View file

@ -19,12 +19,13 @@
#define CHIAKI_CHIAKI_CLI_H
#include <chiaki/common.h>
#include <chiaki/log.h>
#ifdef __cplusplus
extern "C" {
#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
}

View file

@ -17,20 +17,26 @@
#include <chiaki-cli.h>
#include <chiaki/discovery.h>
#include <argp.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
static char doc[] = "Send a PS4 discovery request.";
#define ARG_KEY_HOST 'h'
static struct argp_option options[] = {
{ "ip", 'i', "IP", 0, "IP to send discovery request to", 0 },
{ 0 }
{ "host", ARG_KEY_HOST, "Host", 0, "Host to send discovery request to", 0 },
{ 0 }
};
typedef struct arguments
{
char *ip;
const char *host;
} Arguments;
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)
{
case 'i':
arguments->ip = arg;
case ARG_KEY_HOST:
arguments->host = arg;
break;
case ARGP_KEY_ARG:
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 };
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 };
error_t r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
if(r != 0)
error_t argp_r = argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &arguments);
if(argp_r != 0)
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;
}
// TODO
printf("run discovery\n");
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(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;
}

View file

@ -29,11 +29,19 @@ static const char doc[] =
"Supported commands are:\n"
" discover Discover Consoles.\n";
#define ARG_KEY_VERBOSE 'v'
static struct argp_option options[] = {
{ "verbose", ARG_KEY_VERBOSE, NULL, 0, "Verbose Logging", 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)
return 1;
@ -47,7 +55,7 @@ static int call_subcmd(struct argp_state *state, const char *name, int (*subcmd)
return 1;
snprintf(argv[0], l, "%s %s", state->name, name);
int r = subcmd(argc, argv);
int r = subcmd(state->input, argc, argv);
free(argv[0]);
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)
{
Context *ctx = state->input;
switch(key)
{
case ARG_KEY_VERBOSE:
ctx->log.level_mask = CHIAKI_LOG_ALL;
break;
case ARGP_KEY_ARG:
if(strcmp(arg, "discover") == 0)
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[])
{
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;
}

View file

@ -19,8 +19,6 @@ add_executable(chiaki
src/streamwindow.cpp
include/videodecoder.h
src/videodecoder.cpp
include/discoverycmd.h
src/discoverycmd.cpp
include/mainwindow.h
src/mainwindow.cpp
include/dynamicgridwidget.h
@ -39,7 +37,7 @@ add_executable(chiaki
src/avopenglframeuploader.cpp)
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 Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Multimedia Qt5::OpenGL)
if(CHIAKI_GUI_ENABLE_QT_GAMEPAD)

View file

@ -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

View file

@ -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;
}

View file

@ -1,10 +1,11 @@
#include <streamwindow.h>
#include <videodecoder.h>
#include <discoverycmd.h>
#include <mainwindow.h>
#include <streamsession.h>
#include <chiaki-cli.h>
#include <chiaki/session.h>
#include <chiaki/base64.h>
@ -15,7 +16,16 @@
#include <QAudioOutput>
#include <QAudioFormat>
#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 RunMain(QApplication &app);
@ -35,10 +45,15 @@ int main(int argc, char *argv[])
QApplication::setApplicationName("Chiaki");
QCommandLineParser parser;
parser.setOptionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsPositionalArguments);
parser.addHelpOption();
parser.addPositionalArgument("command", "stream or discover");
parser.addPositionalArgument("host", "Address to connect to");
QStringList cmds;
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");
parser.addOption(regist_key_option);
@ -62,13 +77,13 @@ int main(int argc, char *argv[])
if(args.length() == 0)
return RunMain(app);
if(args.length() < 2)
parser.showHelp(1);
QString host = args[1];
if(args[0] == "stream")
{
if(args.length() < 2)
parser.showHelp(1);
QString host = args[1];
StreamSessionConnectInfo connect_info;
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())
parser.showHelp(1);
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
{