diff --git a/doc/footer b/doc/footer new file mode 100644 index 0000000000000000000000000000000000000000..505654ab7b32158c1bb022e91b6a5b4b52ce3034 --- /dev/null +++ b/doc/footer @@ -0,0 +1,40 @@ +.SH "AUTHOR AND AVAILABILITY" +Lektor is a karaoke player for POSIX compliant systems (i.e. not MS-Windows) +writen initially in C. Some may call it Lektor mk 7. It was writen by Hubert +\'Taiite' HIRTZ, Maël 'Kubat' MARTIN and Louis 'Elliu' GOYARD. These people +also helped: Loïc 'Sting' ALLÈGRE and Etienne 'Pelle' BRATEAU. +.PP +The up\-to\-date source code is available via Git from Gitlab\&. See +\fBhttps://git\&.iiens\&.net/martin2018/lektor\fP. The source code is +provided under the \fIISC\fP licence. +.fi +.SH "RELATED SITES AND THE LEKTOR FAQ" +Just see one of the dev from lektor or a bakateux if you have some questions +about lektor. +.PP +.PD 0 +.TP +\fBhttps://kurisu.iiens.net\fP The depo site for the karaoke base +.TP +\fBhttps://manga.iiens.net\fP The home website for the Bakaclub +.PD +.SH "FILES" +.PD 0 +.TP +\fB$HOME/.config/lektor/lektor.ini\fP general config file for the user +.TP +\fB/home/kara/\fP default prefix for the bakabase +.TP +\fB/home/kara/kara.db\fP default sqlite3 base for the bakabase +.PD +.SH "SEE ALSO" +\fIlektor\fP(1), +\fIlektord\fP(1), +\fIlktadm\fP(1), +\fIlkt\fP(1), +\fImpc\fP(1), +\fImpd\fP(1), +\fImeson\fP(1) +.PP +\fBIEEE Standard for information Technology \- +Portable Operating System Interface (POSIX)\fP diff --git a/doc/header b/doc/header new file mode 100644 index 0000000000000000000000000000000000000000..04e76afaac69806019422f6b6b7aec0e478d3c17 --- /dev/null +++ b/doc/header @@ -0,0 +1 @@ +.TH "___PAGE___" "1" "___DATE___" "LEKTOR MK 7" diff --git a/doc/lektor.1 b/doc/lektor.1 new file mode 100644 index 0000000000000000000000000000000000000000..aa5f9cdaa5734ce3d24237493f3ad0d9cc7b2336 --- /dev/null +++ b/doc/lektor.1 @@ -0,0 +1,83 @@ +.SH "NAME" +lektor \- the lektor karaoke player +.SH "OVERVIEW" +Lektor is a collection of pragram, a daemon a client and an administrator +used to play karaoker from the bakabase. +.PP +You may be interested in other related programs like: +.PP +.PD 0 +.TP +\fIlektord\fP The lektor daemon +.TP +\fIlktadm\fP Administration of lektor from a separate executable +.TP +\fIlkt\fP A standard client for lektord +.PD +.SH "DESCRIPTION" +lektor is a replacement of old bash scripts present on \fISakura\fP (now +\fIShinSakura\fP). It allows interaction from the network with a \fIMPD\fP +compatible protocol even if functionnalities may differ. +.PP +Here is a list of functionnalities offered by lektor: +.PP +.PD 0 +.TP +.PD +\fBBase synchronisation\fP +The entire base can be syncrhonised from \fIKurisu\fP. +.TP +\fBManipulation over the network\fP +Lektord can be piloted over the network with \fBlkt\fP. +.TP +\fBPlaylists and stickers\fP +Reading and searching through the base can be facilitated by creating +\fIplaylist\fP and using \fIstickers\fP (\fIMPD\fP version of tags). +.PP +.SH "SUPPORTED URIS" +When searching the database, the following URIs are supported by lektor. Those +URIs are hidden, you should not use them, but here is some documentation about +them. +.PP +.PD 0 +.TP +.PD +\(bu +\fBid://${arg}\fP +the \fBarg\fP should be the id of the kara in the sqlite3 database. +.TP +\(bu +\fBfs://${arg}\fP +the \fBarg\fP should be a part of the path to the kara. +.TP +\(bu +\fBlang://${arg}\fP / \fBlanguage://${arg}\fP +the \fBarg\fP should be the language of the kara. +.TP +\(bu +\fBtype://${arg}\fP +the \fBarg\fP should be the type of the kara. +.TP +\(bu +\fBcat://${arg}\fP / \fBcategory://${arg}\fP +the \fBarg\fP should be the category of the kara. +.TP +\(bu +\fBauthor://${arg}\fP +the \fBarg\fP should be the author of the kara +.TP +\(bu +\fBquery://${arg}\fP +the \fBarg\fP should be a sqlite3 query. The formating string on which the query +is applied is like \fB"${cat}/${source} - ${type}${song_num?} - ${title}"\fP. +You usually want to do this. +.PP +.SH "SUPPORTED LANGUAGES" +The supported languages in lektor are: \fBjp\fP, \fBfr\fP, \fBsp\fP, \fBen\fP, +\fBlatin\fP, \fBit\fP, \fBru\fP, \fBmulti\fP and \fBundefined\fP. +.SH "SUPPORTED TYPES" +The supported types in lektor are: \fBOP\fP, \fBED\fP, \fBIS\fP, \fBAMV\fP, +\fBVOCA\fP, \fBMV\fP, \fBPV\fP and \fBLIVE\fP. +.SH "SUPPORTED CATEGORIES" +The supported categories in lektor are: \fBvo\fP, \fBva\fP, \fBcdg\fP, +\fBamv\fP, \fBvocaloid\fP and \fBautres\fP. diff --git a/doc/lektord.1 b/doc/lektord.1 index 66245cf2900548f5b488318b667df9bdbb787b76..5db48c628aee3f3345ca6d8521d5b17e4b89ae93 100644 --- a/doc/lektord.1 +++ b/doc/lektord.1 @@ -1,4 +1,3 @@ -.TH "LEKTORD" "1" "February 12, 2020" "lektord 0\&.1\&.0" .SH "NAME" lektord \- the lektor daemon .SH "OVERVIEW" @@ -18,26 +17,6 @@ You may be interested in other related programs like: Lektor allows one to interactivelly and remotly interact with the player. The lektor daemon is mpd compatible, even if some functionnalities may differ. You can almost use \fBmpc\fP with lektord. -.SH "AUTHOR" -Lektor is a karaoke player for POSIX compliant systems (i.e. not MS-Windows) -writen initially in C. Some may call it Lektor mk 7. It was writen by Hubert -\'Taiite' HIRTZ, Maël 'Kubat' MARTIN and Louis 'Elliu' GOYARD. -.SH "AVAILABILITY" -I don't know what to do in this section. -.PP -The up\-to\-date source code is available via Git from Gitlab\&. See -\fBhttps://git\&.iiens\&.net/martin2018/lektor\fP -.fi -.SH "THE LEKTOR FAQ" -Just see one of the dev from lektor or a bakateux. -.SH "RELATED SITES" -.PP -.PD 0 -.TP -\fBhttps://kurisu.iiens.net\fP The depo site for the karaoke base -.TP -\fBhttps://manga.iiens.net\fP The home website for the Bakaclub -.PD .SH "INSTALLATION" You may install lektor from source like this: .sp @@ -82,67 +61,3 @@ by meson during the install), you should just use: .PP You should edit the configuration file to set correct path to \fB.so\fP file, those files are modules for the window of lektord. -.SH "SUPPORTED URIS" -When searching the database, the following URIs are supported by lektor. Those -URIs are hidden, you should not use them, but here is some documentation about -them. -.PP -.PD 0 -.TP -.PD -\(bu -\fBid://${arg}\fP -the \fBarg\fP should be the id of the kara in the sqlite3 database. -.TP -\(bu -\fBfs://${arg}\fP -the \fBarg\fP should be a part of the path to the kara. -.TP -\(bu -\fBlang://${arg}\fP / \fBlanguage://${arg}\fP -the \fBarg\fP should be the language of the kara. -.TP -\(bu -\fBtype://${arg}\fP -the \fBarg\fP should be the type of the kara. -.TP -\(bu -\fBcat://${arg}\fP / \fBcategory://${arg}\fP -the \fBarg\fP should be the category of the kara. -.TP -\(bu -\fBauthor://${arg}\fP -the \fBarg\fP should be the author of the kara -.TP -\(bu -\fBquery://${arg}\fP -the \fBarg\fP should be a sqlite3 query. The formating string on which the query -is applied is like \fB"${cat}/${source} - ${type}${song_num?} - ${title}"\fP. -You usually want to do this. -.PP -.SH "SUPPORTED LANGUAGES" -The supported languages in lektor are: \fBjp\fP, \fBfr\fP, \fBsp\fP, \fBen\fP, -\fBlatin\fP, \fBit\fP, \fBru\fP, \fBmulti\fP and \fBundefined\fP. -.SH "SUPPORTED TYPES" -The supported types in lektor are: \fBOP\fP, \fBED\fP, \fBIS\fP, \fBAMV\fP, -\fBVOCA\fP, \fBMV\fP, \fBPV\fP and \fBLIVE\fP. -.SH "SUPPORTED CATEGORIES" -The supported categories in lektor are: \fBvo\fP, \fBva\fP, \fBcdg\fP, -\fBamv\fP, \fBvocaloid\fP and \fBautres\fP. -.SH "FILES" -.PD 0 -.TP -\fB$HOME/.config/lektor/lektor.ini\fP general config file for the user -.TP -\fB/home/kara/\fP default prefix for the bakabase -.TP -\fB/home/kara/kara.db\fP default sqlite3 base for the bakabase -.PD -.SH "SEE ALSO" -\fIlktadm\fP(1), -\fIlkt\fP(1), -\fImpc\fP(1), -\fImpd\fP(1) -.PP -\fBIEEE Standard for information Technology \- -Portable Operating System Interface (POSIX)\fP diff --git a/doc/lkt.1 b/doc/lkt.1 new file mode 100644 index 0000000000000000000000000000000000000000..153952886d9b2be3df10003ebaae9e221a8f783f --- /dev/null +++ b/doc/lkt.1 @@ -0,0 +1,224 @@ +.SH "NAME" +lkt \- the lektor command line client + +.SH "OVERVIEW" +\fBlkt\fP is the \fBlektord\fP client, much like \fBmpc\fP but with +more functionnalities like \fIplaylists\fP and \fIstickers\fP management. +.PP +Commands can be used with the minimal name that permit them to be +distinguished from others commands. Thus, it is possible to use the +string \fIadm\fP as an alias for \fIadmin\fP. This is like cisco switch +command line interface. +.PP +You may be interested in other related programs like: +.PP +.PD 0 +.TP +\fIlektord\fP The lektor daemon +.TP +\fIlktadm\fP Administration of lektor from a separate executable +.PD + +.SH "COMMANDS" +Here are the \fBlkt\fP commands: + +.PP +\fIBASE-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBcurrent\fP +Prints informations about the currently playing kara. Can be used to +display the current kara in a status bar like \fBxmobar\fP or in the +\fBi3 panel\fP +.TP +\fBplay\fP [index] +Toggle play/pause state. If the playback is stopped, start at a possibly +specified index +.TP +\fBnext\fP +Play next kara in the queue +.TP +\fBprevious\fP +Play the previous kara in the queue +.TP +\fBshuffle\fP +Shuffle the queue. If the state was stoppped, play from the first kara +in the queue. If lektor was already playing a kara, it will play it +from the begening. The current kara will be placed in first position +in the queue. +.TP +\fBstatus\fP +Prints information about the state of lektor and the currently playing kara +.TP +\fBstop\fP +Stop the playback and reading the queue, the state is now \fIstopped\fP. +.PP +\fIPLAYLIST-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBplt create\fP <plt-name> +Creates a playlist, do nothing if it was already present +.TP +\fBplt destroy\fP <plt-name> +Delete a playlist with all its content, do nothing if the playlist didn't exists +.TP +\fBplt delete\fP <plt-name> <query> +Deletes karas from a playlist with a valid \fIquery\fP +.TP +\fBplt add\fP <plt-name> <query> +Adds karas to a playlist with a valid \fIquery\fP +.PP + +\fIQUEUE-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBqueue\fP [count] +Prints the names and ids of the next karas in the queue +.TP +\fBqueue pos\fP <pos | from:to> +Prints the names and ids of karas in the queue. Karas can be designated by +their position or with a range +.TP +\fBqueue pop\fP +Delete the currently playing kara from the queue and pass to the next one. +This can work only if the currently playong kara is not the last +.TP +\fBqueue add\fP <query> +Add karas to the queue at the end of it with a valid query +.TP +\fBqueue seek\fP <id> +Goto to the kara with the specified id in the queue +.TP +\fBqueue delete\fP <id> +Delete karas from the playlist with their id. You can't delete the currently +playing kara, for that use the \fBpop\fP queue command +.TP +\fBqueue clear\fP +Clear the queue and set the state to \fIstopped\fP +.TP +\fBqueue crop\fP +Crop the queue, delete every kara from it appart from the currently +playing one +.PP + +\fISEARCH-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBsearch get\fP <query> +Search and prints the kara that correspond to the query in the database +.TP +\fBsearch add\fP <query> +Search, prints and add to the queue the karas that match the query +.TP +\fBsearch insert\fP <query> +Search, prints and insert into the queue the karas that match the query +.TP +\fBsearch plt\fP <plt-name> <query> +Search, prints and add to an existing playlist the karas that match +the query +.TP +\fBsearch count\fP <query> +Search and prints the number of karas that match the query +.TP +\fBsearch queue\fP <query> +Search in the queue and prints the karas that match the query +.PP + +\fIADMIN-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBadmin ping\fP +Pings the lektord daemon, prints \fIOK\fP only if the ping succeeded +.TP +\fBadmin kill\fP +Kill the lektord daemon +.TP +\fBadmin restart\fP +Try to restart the lektord daemon +.TP +\fBadmin rescan\fP +Rescan karas from the filesystem. New karas that are not in the database +will be added to it. Don't synchronize from the repo +.TP +\fBadmin update\fP +Update the base from the \fIKurisu\fP repo. Don't scan for new files in +the filesystem +.PP + +.SH "OPTIONS" +Options can be passed to \fBlkt\fP before specifying the command in a +\fIoption=value\fP format. This is done this way to allow one to make +an alias of the \fBlkt\fP command. +.PP +The possible options are the following: +.PP +.PD 0 +.TP +.PD +\fBhost\fP +The hostname or the IP of the machine where the \fBlektord\fP daemon +is running +.TP +\fBport\fP +The port on which the \fBlektord\fP daemon is listening +.TP +\fBpwd\fP +The password to use for commands that require authentification. This is the +case of most of the \fIadmin\fP commands +.PP + +.SH "QUERIES" +Queries are a way of listing karas in the database. They are composed of a +type and the next of the line is the SQL regex that the kara must verify. +In SQL regexes, the wildcard is the "%" character and the jocker the +character "_". Queries are case insensitive. +.PP +Valid types for a query are the following: \fIid\fP, \fIlanguage\fP, or +\fIlang\fP, \fItype\fP, \fIcat\fP or \fIcategory\fP, \fIauthor\fP, \fIquery\fP, +\fIsource\fP and \fItitle\fP. +.PP +For the type \fItype\fP, the valid values are the following: \fIOP\fP, +\fIED\fP, \fIIS\fP, \fIAMV\fP, \fIVOCA\fP, \fIMV\fP, \fIPV\fP +and \fILIVE\fP. +.PP +For the type \fIlanguage\fP or \fIlang\fP, the valid values are the following: +\fIjp\fP, \fIfr\fP, \fIsp\fP, \fIen\fP, \fIlatin\fP, \fIit\fP, \fIru\fP, +\fImulti\fP and \fIundefined\fP. +.PP +For the \fIcat\fP or \fIcategory\fP type, the valid values are the following: +\fIvo\fP, \fIva\fP, \fIcdg\fP, \fIamv\fP, \fIvocaloid\fP and \fIautres\fP. +.PP +Here are some examples of queries: +.PP +.PD 0 +.TP +.PD +\fBtype OP\fP +Select karas that are openings +.TP +\fBauthor k%\fP +Select karas where the author begin with the character "k" +.PP + +.SH "EXAMPLES" +Valid invocations of the \fBlkt\fP command are the following: +.PP +.PD 0 +.TP +.PD +\fBlkt host=sakura port=6601 pwd=toto admin restart\fP +Restart the lektord daemon on the \fIsakura\fP PC. This daemon is listening on +the port \fI6601\fP and the password of the admin user is \fItoto\fP +.TP +\fBlkt q a author krocoh\fP +Add kara that Krocoh has done to the queue diff --git a/doc/lktadm.1 b/doc/lktadm.1 new file mode 100644 index 0000000000000000000000000000000000000000..f7309e8b9180698700a7f169fd75555b76c59b03 --- /dev/null +++ b/doc/lktadm.1 @@ -0,0 +1,64 @@ +.SH "NAME" +lktadm \- the lektor administration tool +.SH "OVERVIEW" +Commands can be used with the minimal name that permit them to be +distinguished from others commands. Thus, it is possible to use the +string \fIdow\fP as an alias for \fIdownload\fP. This is like cisco switch +command line interface. +.PP +You may be interested in other related programs like: +.PP +.PD 0 +.TP +\fIlektord\fP The lektor daemon +.TP +\fIlkt\fP A standard client for lektord +.PD + +.SH "COMMANDS" +Here are the \fBlkt\fP commands: + +.PP +\fIBASE-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBget\fP <id> +Get and display the metadata of a kara by its id. You must have access to +the \fIKurisu\fP repo +.TP +\fBdownload\fP <id> <filepath> +Download a kara from kurisu and save it to the specified path +.TP +\fBcat\fP <filepath> +Display the metadata of a kara specified by the its path +.TP +\fBconf\fP +Prints the default configuration file to stdout + +.PP +\fIINITIALISATION-COMMANDS\fP +.PP +.PD 0 +.TP +.PD +\fBinit database\fP +Create the empty database with the correct SQL schema. You need a valid +configuration file to do that +.TP +\fBinit populate\fP +Populate the database with kara on the filesystem. You need a valid +configuration file and a valid database for that +.TP +\fBinit metadata\fP +Write the correct metadata to kara in the filesystem. For that you +need a valid configuration file and a specific organisation of the files. +The best way of doing it is using the \fIadmin update\fP command with +\fBlkt\fP. This command is present but depracted +.TP +\fBinit file\fP +Write correct metadata to a kara in the filesystem. You need a specific +file organisation for that command to work. It is depracted but present +for debuging purpose +.PP diff --git a/inc/lektor/cmd.h b/inc/lektor/cmd.h index de18772650d1e335c7fdfc9e1aa937a4ee2e555e..7861e0e6b45e86ea10a910fc8b10ce6527107bf8 100644 --- a/inc/lektor/cmd.h +++ b/inc/lektor/cmd.h @@ -16,12 +16,12 @@ typedef void (*lkt_cmd_callback)(struct lkt_cmd_args *); struct lkt_cmd_opt { const char *name; lkt_cmd_callback call; - const char *help; - struct lkt_cmd_opt *sub; }; /* Parse the command line with the list of options. No parameter may be NULL. Does not return. */ -noreturn void lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **argv, void (*help)(void)); +noreturn void lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **argv); -void lkt_cmd_help(struct lkt_cmd_opt *opts, const char *name); +/* Must be setted for the lkt_cmd_parse function to display the correct help + in case of errors. */ +extern const char *executable_name; diff --git a/meson.build b/meson.build index 0e421b7bb22354e6a359dacc415542c66d8aa7b6..3a06d3244e75a7e7d510f9cf1145b1ffa5bae427 100644 --- a/meson.build +++ b/meson.build @@ -9,7 +9,6 @@ project( 'lektor' , 'strip=true' , 'debug=true' , 'buildtype=debug' - , 'b_sanitize=undefined' ] ) @@ -84,16 +83,21 @@ mthread_deps = [ declare_dependency( link_with: static_library( 'mthread' , include_directories: includes , dependencies: [ common_deps ] ) ] -initsql_deps = [ declare_dependency( link_with: static_library( 'initsql' - , [ custom_target('init.c' - , output: 'sql_init.c' - , input: 'scripts/init.sql' - , command: [ find_program('xxd'), '-i', '@INPUT@', '@OUTPUT@']) ] ) ) ] +generated_deps = [ declare_dependency( link_with: static_library( 'generated' + , [ custom_target( 'sqlinit' + , output: 'sqlinit.c' + , input: 'scripts/init.sql' + , command: [ find_program('xxd'), '-i', '@INPUT@', '@OUTPUT@' ] ) ] + , [ custom_target( 'manpath' + , output: 'manpath.c' + , input: 'scripts/getmanpath.sh' + , command: [ find_program('scripts/getmanpath.sh'), '@OUTPUT@' ] ) ] + ) ) ] lib = static_library( 'lektor' , files(core_sources) , include_directories: includes - , dependencies: [ core_deps, libdl, common_deps, mthread_deps, initsql_deps ] ) + , dependencies: [ core_deps, libdl, common_deps, mthread_deps, generated_deps ] ) bin_deps = [ declare_dependency( link_with: lib, include_directories: includes) ] @@ -114,6 +118,7 @@ lktadm = executable( 'lktadm' lkt = executable( 'lkt' , files('src/main/lkt.c', 'src/cmd.c', 'src/common.c') , include_directories: includes + , dependencies: [ generated_deps ] , install: true ) # X11 window module @@ -138,6 +143,27 @@ if dep_sdl.found() and dep_mpv.found() , install_dir: 'lib/lektor' ) endif +# Man pages +man_sh = find_program('scripts/man.sh') +man_header = run_command('realpath', 'doc/header').stdout().strip() +man_footer = run_command('realpath', 'doc/footer').stdout().strip() +man_files = [ [ 'lektord', '1' ] + , [ 'lektor', '1' ] + , [ 'lktadm', '1' ] + , [ 'lkt', '1' ] + ] + +foreach man: man_files + man_name = man.get(0) + man_section = man.get(1, '1') + custom_target( '@0@.@1@'.format(man_name, man_section) + , input: 'doc/@0@.@1@'.format(man_name, man_section) + , output: '@0@.@1@'.format(man_name, man_section) + , command: [ man_sh, '@INPUT@', '@OUTPUT@', man_header, man_footer ] + , depend_files: [ man_header, man_footer ] + , install: true + , install_dir: join_paths(get_option('mandir'), 'man@0@'.format(man_section)) ) +endforeach + # Install -install_man('doc/lektord.1') meson.add_install_script('scripts/install.sh') diff --git a/scripts/getmanpath.sh b/scripts/getmanpath.sh new file mode 100644 index 0000000000000000000000000000000000000000..84a088cea05c9aa6c413fb4700f32ecc11574b2e --- /dev/null +++ b/scripts/getmanpath.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +# $1: output file +[ $# -ne 1 ] && exit 1 +echo "const char *man_executable_path = \"$(which man)\";" > "$1" diff --git a/scripts/man.sh b/scripts/man.sh new file mode 100755 index 0000000000000000000000000000000000000000..50bff11fac7f998288ee5861e293afc1d174c3a5 --- /dev/null +++ b/scripts/man.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# $0: script name +# $1: input +# $2: output +# $3: header +# $4: footer +[ $# -ne 4 ] && exit 1 +[ "$1" == "$2" ] && exit 2 + +# Global variables +HEADER="$3" +FOOTER="$4" +INPUT="$1" +OUTPUT="$2" + +# Functions +function the_day() { + # $1: file + # $2: what to replace with the date + local DATE=$(date +'%B %d, %Y') + sed -i "s/$2/$DATE/g" "$1" +} + +function the_page() { + # $1: file + # $2: what to replace with the date + FILE=$(basename "$1") + FILE="${FILE%.*}" + FILE="${FILE^^}" + sed -i "s/$2/$FILE/g" "$1" +} + +function mk_manpage() { + # $1: input + # $2: output + cat $HEADER > $2 + cat $1 >> $2 + cat $FOOTER >> $2 + the_day "$2" '___DATE___' + the_page "$2" '___PAGE___' +} + +mk_manpage "$INPUT" "$OUTPUT" +exit 0 diff --git a/src/cmd.c b/src/cmd.c index ae46c8b299db796e69d335b267d9ffdfa827b2db..4a38bddccedf921471fde4fc149ccc5fc8f28a01 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -9,15 +9,29 @@ #include <stdio.h> #include <unistd.h> +const char *executable_name = NULL; +extern const char *man_executable_path; + +noreturn void +help__() +{ + if (!executable_name) + exit(EXIT_FAILURE); + const char *const args[] = { man_executable_path, executable_name }; + execv(args[0], (char *const *) args); + exit(EXIT_FAILURE); +} + noreturn void -lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **argv, void (*help)(void)) +lkt_cmd_parse(struct lkt_cmd_opt *opts, int argc, const char **argv) { int count = 0, is_ok, offset = 0; struct lkt_cmd_opt *it = opts; lkt_cmd_callback call[2] = { NULL, NULL }; - if (argc == 0 || *argv == NULL) - goto no_args; + if (argc == 0 || *argv == NULL || strcasecmp(argv[0], "help") || + strcasecmp(argv[0], "--help") || strcasecmp(argv[0], "-help")) + goto help; /* Find the command */ while (it && it->name) { @@ -56,46 +70,10 @@ not_found: LOG_ERROR_SCT("COMMAND", "Command '%s' could not be found", argv[0]); exit(EXIT_FAILURE); -no_args: - lkt_cmd_help(opts, NULL); - if (help) - help(); - exit(EXIT_SUCCESS); +help: + help__(); not_exclusive: LOG_ERROR_SCT("COMMAND", "Failed to determine option, '%s' not exclusive", argv[0]); exit(EXIT_FAILURE); } - -void -lkt_cmd_help(struct lkt_cmd_opt *opts, const char *name) -{ - struct lkt_cmd_opt *it = opts; - int offset = 0, max_len = 1; - - /* Get the maximan argument len */ - while (it && it->name) { - int len = strlen(it->name); - max_len = MAX(max_len, len); - it = opts + (++offset); - } - - /* Print the options */ - it = opts; - offset = 0; - printf("COMMAND %s:\n", name); - while (it && it->name) { - printf("\t%*s %s\n", max_len, it->name, it->help); - it = opts + (++offset); - } - - /* Prints the sub commands help */ - it = opts; - offset = 0; - write(1, "\n", sizeof(char)); - while (it && it->name) { - if (it->sub) - lkt_cmd_help(it->sub, it->name); - it = opts + (++offset); - } -} diff --git a/src/config.c b/src/config.c index e9348887180bb8790c50fc7664f06de2dd608e80..cfc6e2b3eaef579628ad42f7a251ba7be3880aeb 100644 --- a/src/config.c +++ b/src/config.c @@ -15,7 +15,7 @@ #include <sys/stat.h> #include <limits.h> -static inline int +int load_so(const char *const mod_path, const char *const mod_init, void *mod) { /* An init function takes two arguments: the module pointer and a void* diff --git a/src/database/playlist.c b/src/database/playlist.c index 0dbb4ac59036762122a1fa11bf38f90e1b430624..2079ec836c5b8433595b031cee830a1ec7b0f2c6 100644 --- a/src/database/playlist.c +++ b/src/database/playlist.c @@ -99,7 +99,7 @@ database_plt_export(volatile sqlite3 *db, const char *name) "( kara_id INTEGER PRIMARY KEY NOT NULL CHECK(kara_id > 0) );"; char SQL_STMT[LKT_MAX_SQLITE_STATEMENT]; int code, ret = false; - sqlite3_stmt *stmt; + sqlite3_stmt *stmt = NULL; if (is_sql_str_invalid(name)) { LOG_ERROR("The playlist name '%s' is invalid", name); diff --git a/src/database/queue.c b/src/database/queue.c index 7adbac37caf29a97d7c426ef2ca4af91bf2c7cc2..8cf4fae3838e6d8f98d1414cbce037c8ff9caa15 100644 --- a/src/database/queue.c +++ b/src/database/queue.c @@ -643,7 +643,7 @@ bool database_queue_seekid(volatile sqlite3 *db, int id, int *out_pos) { static const char *SQL_STMT = "SELECT position FROM queue_ WHERE kara_id = ? LIMIT 1"; - int ret; + int ret = 0; sqlite3_stmt *stmt; SQLITE_PREPARE(db, stmt, SQL_STMT, error); diff --git a/src/main/lkt.c b/src/main/lkt.c index 6ed06b2230d591b1e0892b0d3641df14e0efbe82..8ea952bd2556dd90061d75f69a3ad4465eed3293 100644 --- a/src/main/lkt.c +++ b/src/main/lkt.c @@ -28,32 +28,6 @@ #define STR_MATCH(str1, str2) (! strcasecmp(str1, str2)) #define STR_NMATCH(str1, str2, n) (! strncasecmp(str1, str2, n)) -/* The help. */ - -noreturn void -help(void) -{ - static const char *help_str = - "OPTIONS:\n" - " host named of the lektor's host, can be resolved\n" - " port port on which lektor is listening\n" - "\n" - " options most be passed as one word (no spaced), such as the following:\n" - " % lkt host=sakura port=6601 play\n" - "\n" - "QUERY:\n" - " A query is passed in argument of a COMMAND and is composed of:\n" - " - The first word must be the type\n" - " - the rest is used for the sqlite regex\n" - " Supported types are: title, [a]ny, source, [auth]or, [lang]uage, type, title\n" - "\n" - "RANGE:\n" - " A range is specified like BEGIN:END which implies from BEGIN to END included\n" - "\n"; - write(1, help_str, strlen(help_str)); - exit(EXIT_SUCCESS); -} - static noreturn inline void fail(const char *message) { @@ -974,40 +948,40 @@ search_queue__(struct lkt_cmd_args *args) /* Parsing stuff. */ static struct lkt_cmd_opt options_queue[] = { - { .name = "pos", .call = queue_pos__, .help = "Display the content of the queue by a range or a position" }, - { .name = "pop", .call = queue_pop__, .help = "Pop the current kara in the queue" }, - { .name = "add", .call = queue_add__, .help = "Add karas to the queue by a query" }, - { .name = "seek", .call = queue_seek__, .help = "Seek a kara in the queu by a query" }, - { .name = "delete", .call = queue_delete__, .help = "Delete a kara by its id in the queue" }, - { .name = "clear", .call = queue_clear__, .help = "Clear the queue" }, - { .name = "crop", .call = queue_crop__, .help = "Crop the queue" }, + { .name = "pos", .call = queue_pos__ }, + { .name = "pop", .call = queue_pop__ }, + { .name = "add", .call = queue_add__ }, + { .name = "seek", .call = queue_seek__ }, + { .name = "delete", .call = queue_delete__ }, + { .name = "clear", .call = queue_clear__ }, + { .name = "crop", .call = queue_crop__ }, LKT_OPT_DEFAULT(queue_list__), }; static struct lkt_cmd_opt options_plt[] = { - { .name = "add", .call = plt_add__, .help = "Add something to a playlist" }, - { .name = "delete", .call = plt_delete__, .help = "Delete karas from a playlist with a query" }, - { .name = "destroy", .call = plt_destroy__, .help = "Delete a playlist" }, - { .name = "create", .call = plt_create__, .help = "Create a playlist" }, + { .name = "add", .call = plt_add__ }, + { .name = "delete", .call = plt_delete__ }, + { .name = "destroy", .call = plt_destroy__ }, + { .name = "create", .call = plt_create__ }, LKT_OPT_NULL, }; static struct lkt_cmd_opt options_search[] = { - { .name = "get", .call = search_get__, .help = "Prints the results of the query" }, - { .name = "add", .call = search_add__, .help = "Prints and add the results to the queue" }, - { .name = "insert", .call = search_insert__, .help = "Prints and inserts at the top of the queue the results of the query" }, - { .name = "plt", .call = search_plt__, .help = "Search inside a playlist and prints the results" }, - { .name = "count", .call = search_count__, .help = "Count the number of karas matching the query and prints it" }, - { .name = "queue", .call = search_queue__, .help = "Search in the queue and prints the results of the query" }, + { .name = "get", .call = search_get__ }, + { .name = "add", .call = search_add__ }, + { .name = "insert", .call = search_insert__ }, + { .name = "plt", .call = search_plt__ }, + { .name = "count", .call = search_count__ }, + { .name = "queue", .call = search_queue__ }, LKT_OPT_NULL, }; static struct lkt_cmd_opt options_admin[] = { - { .name = "ping", .call = ping__, .help = "Only pings the server" }, - { .name = "kill", .call = kill__, .help = "Kills the lektord server" }, - { .name = "restart", .call = restart__, .help = "Restarts the lektord server" }, - { .name = "rescan", .call = rescan__, .help = "Scan the filesystem and update the database with present files" }, - { .name = "update", .call = update__, .help = "Update the database with files present on Kurisu" }, + { .name = "ping", .call = ping__ }, + { .name = "kill", .call = kill__ }, + { .name = "restart", .call = restart__ }, + { .name = "rescan", .call = rescan__ }, + { .name = "update", .call = update__ }, LKT_OPT_NULL, }; @@ -1017,7 +991,7 @@ admin__(struct lkt_cmd_args *args) if (args->argc == 0) fail("Invalid argument, you must specify a sub command for the admin command"); - lkt_cmd_parse(options_admin, args->argc, args->argv, help); + lkt_cmd_parse(options_admin, args->argc, args->argv); } noreturn void @@ -1026,7 +1000,7 @@ queue__(struct lkt_cmd_args *args) if (args->argc == 0) queue_list__(args); - lkt_cmd_parse(options_queue, args->argc, args->argv, help); + lkt_cmd_parse(options_queue, args->argc, args->argv); } noreturn void @@ -1035,7 +1009,7 @@ search__(struct lkt_cmd_args *args) if (args->argc == 0) fail("Invalid argument, you must specify a sub command for the search command"); - lkt_cmd_parse(options_search, args->argc, args->argv, help); + lkt_cmd_parse(options_search, args->argc, args->argv); } noreturn void @@ -1044,21 +1018,21 @@ plt__(struct lkt_cmd_args *args) if (args->argc == 0) fail("Invalid argument, you must specify a sub command for the playlist command"); - lkt_cmd_parse(options_plt, args->argc, args->argv, help); + lkt_cmd_parse(options_plt, args->argc, args->argv); } static struct lkt_cmd_opt options_[] = { - { .name = "current", .call = current__, .help = "Get the current playing song" }, - { .name = "play", .call = play__, .help = "Toggle play/pause, may starts at a specified index" }, - { .name = "next", .call = next__, .help = "Play the next kara in the queue" }, - { .name = "previous", .call = prev__, .help = "Play the previous kara in the queue" }, - { .name = "queue", .call = queue__, .help = "The queue sub-command", .sub = options_queue }, - { .name = "shuffle", .call = shuffle__, .help = "Shuffle the queue" }, - { .name = "status", .call = status__, .help = "Get the status of lektord" }, - { .name = "stop", .call = stop__, .help = "Stop playing the queue, won't close lektord's window" }, - { .name = "plt", .call = plt__, .help = "The playlist sub-command", .sub = options_plt }, - { .name = "search", .call = search__, .help = "The search sub-command", .sub = options_search }, - { .name = "admin", .call = admin__, .help = "Administration commands", .sub = options_admin }, + { .name = "current", .call = current__ }, + { .name = "play", .call = play__ }, + { .name = "next", .call = next__ }, + { .name = "previous", .call = prev__ }, + { .name = "queue", .call = queue__ }, + { .name = "shuffle", .call = shuffle__ }, + { .name = "status", .call = status__ }, + { .name = "stop", .call = stop__ }, + { .name = "plt", .call = plt__ }, + { .name = "search", .call = search__ }, + { .name = "admin", .call = admin__ }, LKT_OPT_NULL, }; @@ -1109,6 +1083,7 @@ parse_args(args_t *args, int argc, const char **argv) int main(int argc, const char **argv) { + executable_name = "lkt"; assert(NULL != setlocale(LC_ALL, "en_US.UTF-8")); /* BECAUSE! */ assert(!signal(SIGPIPE, sigpipe__)); /* Argument checks. */ @@ -1124,5 +1099,5 @@ main(int argc, const char **argv) password = args.pwd; /* Communication with lektor. */ - lkt_cmd_parse(options_, args.argc, args.argv, help); + lkt_cmd_parse(options_, args.argc, args.argv); } diff --git a/src/main/lktadm.c b/src/main/lktadm.c index 84a2de4a56232a28e5539cbbafdbd489ba5ac3ee..df2846b693e25559d8deb3eb7c803af1095b7455 100644 --- a/src/main/lktadm.c +++ b/src/main/lktadm.c @@ -229,30 +229,31 @@ download__(struct lkt_cmd_args *args) } static struct lkt_cmd_opt options_init[] = { - { .name = "database", .call = init_database__, .help = "Create an empty database" }, - { .name = "populate", .call = init_populate__, .help = "Populate database from kara on fs" }, - { .name = "metadata", .call = init_metadata__, .help = "Set mdt for all kara in fs" }, - { .name = "file", .call = init_file__, .help = "Set mdt for a kara by its path" }, + { .name = "database", .call = init_database__ }, + { .name = "populate", .call = init_populate__ }, + { .name = "metadata", .call = init_metadata__ }, + { .name = "file", .call = init_file__ }, LKT_OPT_NULL, }; noreturn void init__(struct lkt_cmd_args *args) { - lkt_cmd_parse(options_init, args->argc, args->argv, NULL); + lkt_cmd_parse(options_init, args->argc, args->argv); } static struct lkt_cmd_opt options[] = { - { .name = "init", .call = init__, .help = "The init sub-command", .sub = options_init }, - { .name = "get", .call = get__, .help = "Get the mdt of a kara by its id" }, - { .name = "download", .call = download__, .help = "Download a kara by its id" }, - { .name = "cat", .call = cat__, .help = "Prints the mdt of a kara on the fs" }, - { .name = "conf", .call = conf__, .help = "Prints out the default config" }, + { .name = "init", .call = init__ }, + { .name = "get", .call = get__ }, + { .name = "download", .call = download__ }, + { .name = "cat", .call = cat__ }, + { .name = "conf", .call = conf__ }, LKT_OPT_NULL, }; int main(int argc, const char **argv) { - lkt_cmd_parse(options, argc - 1, argv + 1, NULL); + executable_name = "lktadm"; + lkt_cmd_parse(options, argc - 1, argv + 1); } diff --git a/src/net/downloader.c b/src/net/downloader.c index 76a9307a49ae7d002b7962c781e0b721d1a2f040..96abec51a631caf426e3a7b6593d4ccfa285a93b 100644 --- a/src/net/downloader.c +++ b/src/net/downloader.c @@ -28,7 +28,7 @@ struct file { int fd; }; -static size_t +size_t write_mem__(char *data, size_t size, size_t nmem, void *user) { size_t realsize = size * nmem; @@ -43,7 +43,7 @@ write_mem__(char *data, size_t size, size_t nmem, void *user) return realsize; } -static size_t +size_t write_disk__(char *data, size_t size, size_t nmem, void *user) { ssize_t realsize = size * nmem; @@ -87,7 +87,8 @@ repo_free(struct lkt_repo *const repo) if (!curl_init) curl_global_cleanup(); } -static inline int + +int safe_json_get_string(struct json_object *jobj, const char *key, char *content, const size_t len) { const char *got; @@ -100,7 +101,7 @@ safe_json_get_string(struct json_object *jobj, const char *key, char *content, c return 0; } -static inline int +int safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret) { struct json_object *field; @@ -111,7 +112,7 @@ safe_json_get_int32(struct json_object *json, const char *key, int32_t *ret) return 0; } -static inline long +long get_digit_number(long i) { int count = 0; @@ -133,7 +134,7 @@ safe_json_get_long(struct json_object *json, const char *key, long *ret) return err; } -static inline int +int __json_sync(struct lkt_repo *const repo, struct json_object **json) { RETURN_UNLESS(json, "Invalid argument", 1); @@ -245,7 +246,7 @@ err: return ret; } -static inline int +int __download_kara(const char *url, const char *path, int override) { CURL *curl_handle; @@ -333,7 +334,7 @@ repo_download_id_sync(struct lkt_repo *const repo, const uint64_t id, const char /* Get all the kara, make them unavailable */ -static inline void +void __handle_got_json(volatile sqlite3 *db, struct lkt_repo *repo, struct json_object *json) { size_t i, len = json_object_array_length(json); @@ -419,7 +420,7 @@ err: free(kara); } -static inline void * +void * __repo_get_all_id_async(void *arg) { struct json_object *json; @@ -434,7 +435,7 @@ __repo_get_all_id_async(void *arg) return NULL; } -inline int +int repo_update(struct lkt_repo *const repo) { return mthread_create(NULL, ATTR_DETACHED, __repo_get_all_id_async, repo); diff --git a/src/net/listen.c b/src/net/listen.c index 35aa74ed7eef616239504b80e3e1788f73e9f021..30f5e5789f7a32e17ff3dbde969b269ae9560e6f 100644 --- a/src/net/listen.c +++ b/src/net/listen.c @@ -147,7 +147,7 @@ command_list_begin(struct lkt_state *srv, size_t c, int list_ok) static int handle_simple_command(struct lkt_state *srv, size_t c, struct lkt_command cmd) { - int err, continuation = 0; + int err = 0, continuation = 0; switch (*lkt_client_get_mask(srv, c)) { case MPD_IDLE_NONE: diff --git a/src/thread.c b/src/thread.c index e4e3f1074945c1cae565f986c7d74efb1439bfc8..8df3d086884a4795827181d716db04b89aa6fef0 100644 --- a/src/thread.c +++ b/src/thread.c @@ -15,7 +15,7 @@ struct __args { struct poller_thread_arg *arg; }; -static void * +void * __start(void *args__) { struct __args *args = (struct __args *) args__; @@ -92,7 +92,7 @@ poller_join(struct poller_thread *th, void **ret) return sta; } -static inline int +int th_append(unsigned int *len, unsigned int *size, void ***cells, pthread_mutex_t *lock, void *ptr) { @@ -121,7 +121,7 @@ end: return ret; } -static inline int +int th_pop(unsigned int *len, void **cells, pthread_mutex_t *lock, void **ptr) { int ret = 1; @@ -139,7 +139,7 @@ end: return ret; } -static inline int +int th_head(unsigned int len, void **cells, pthread_mutex_t *lock, void **ptr) { int ret = 1;