diff --git a/CMakeLists.txt b/CMakeLists.txt index 44adf94..306797f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 2.8) -project (MPDBliss C) +project (Blissify C) add_subdirectory (bliss) @@ -13,20 +13,10 @@ link_directories(${MULTIMEDIA_LIBRARY_DIRS}) add_definitions(${MULTIMEDIA_CFLAGS_OTHER}) add_definitions (-Wall -Wno-long-long -pedantic -std=c99) -add_executable (mpdbliss - ${COMMON_SRC} "main_mpd.c") +add_executable (blissify + ${COMMON_SRC}) -target_link_libraries (mpdbliss - m - sqlite3 - mpdclient - bliss) - - -add_executable (argsbliss - ${COMMON_SRC} "main_args.c") - -target_link_libraries (argsbliss +target_link_libraries (blissify m sqlite3 bliss) diff --git a/include/cmdline.h b/include/cmdline.h deleted file mode 100644 index 2e990ee..0000000 --- a/include/cmdline.h +++ /dev/null @@ -1,194 +0,0 @@ -/** @file cmdline.h - * @brief The header file for the command line option parser - * generated by GNU Gengetopt version 2.22.6 - * http://www.gnu.org/software/gengetopt. - * DO NOT modify this file, since it can be overwritten - * @author GNU Gengetopt by Lorenzo Bettini */ - -#ifndef CMDLINE_H -#define CMDLINE_H - -/* If we use autoconf. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include /* for FILE */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifndef CMDLINE_PARSER_PACKAGE -/** @brief the program name (used for printing errors) */ -#define CMDLINE_PARSER_PACKAGE "MPDBliss" -#endif - -#ifndef CMDLINE_PARSER_PACKAGE_NAME -/** @brief the complete program name (used for help and version) */ -#define CMDLINE_PARSER_PACKAGE_NAME "MPDBliss" -#endif - -#ifndef CMDLINE_PARSER_VERSION -/** @brief the program version */ -#define CMDLINE_PARSER_VERSION "VERSION" -#endif - -/** @brief Where the command line options are stored */ -struct gengetopt_args_info -{ - const char *help_help; /**< @brief Print help and exit help description. */ - const char *version_help; /**< @brief Print version and exit help description. */ - int rescan_flag; /**< @brief Rescan the whole MPD database. (default=off). */ - const char *rescan_help; /**< @brief Rescan the whole MPD database. help description. */ - int rescan_errors_flag; /**< @brief Rescan the errored files from the MPD database. (default=off). */ - const char *rescan_errors_help; /**< @brief Rescan the errored files from the MPD database. help description. */ - int update_flag; /**< @brief Trigger an update. (default=off). */ - const char *update_help; /**< @brief Trigger an update. help description. */ - char * mpd_root_arg; /**< @brief MPD library base path.. */ - char * mpd_root_orig; /**< @brief MPD library base path. original value given at command line. */ - const char *mpd_root_help; /**< @brief MPD library base path. help description. */ - char * host_arg; /**< @brief MPD host. (default=''). */ - char * host_orig; /**< @brief MPD host. original value given at command line. */ - const char *host_help; /**< @brief MPD host. help description. */ - int port_arg; /**< @brief MPD port. (default='0'). */ - char * port_orig; /**< @brief MPD port. original value given at command line. */ - const char *port_help; /**< @brief MPD port. help description. */ - - unsigned int help_given ; /**< @brief Whether help was given. */ - unsigned int version_given ; /**< @brief Whether version was given. */ - unsigned int rescan_given ; /**< @brief Whether rescan was given. */ - unsigned int rescan_errors_given ; /**< @brief Whether rescan-errors was given. */ - unsigned int update_given ; /**< @brief Whether update was given. */ - unsigned int mpd_root_given ; /**< @brief Whether mpd_root was given. */ - unsigned int host_given ; /**< @brief Whether host was given. */ - unsigned int port_given ; /**< @brief Whether port was given. */ - -} ; - -/** @brief The additional parameters to pass to parser functions */ -struct cmdline_parser_params -{ - int override; /**< @brief whether to override possibly already present options (default 0) */ - int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ - int check_required; /**< @brief whether to check that all required options were provided (default 1) */ - int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ - int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ -} ; - -/** @brief the purpose string of the program */ -extern const char *gengetopt_args_info_purpose; -/** @brief the usage string of the program */ -extern const char *gengetopt_args_info_usage; -/** @brief the description string of the program */ -extern const char *gengetopt_args_info_description; -/** @brief all the lines making the help output */ -extern const char *gengetopt_args_info_help[]; - -/** - * The command line parser - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser (int argc, char **argv, - struct gengetopt_args_info *args_info); - -/** - * The command line parser (version with additional parameters - deprecated) - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @param override whether to override possibly already present options - * @param initialize whether to initialize the option structure my_args_info - * @param check_required whether to check that all required options were provided - * @return 0 if everything went fine, NON 0 if an error took place - * @deprecated use cmdline_parser_ext() instead - */ -int cmdline_parser2 (int argc, char **argv, - struct gengetopt_args_info *args_info, - int override, int initialize, int check_required); - -/** - * The command line parser (version with additional parameters) - * @param argc the number of command line options - * @param argv the command line options - * @param args_info the structure where option information will be stored - * @param params additional parameters for the parser - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_ext (int argc, char **argv, - struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params); - -/** - * Save the contents of the option struct into an already open FILE stream. - * @param outfile the stream where to dump options - * @param args_info the option struct to dump - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_dump(FILE *outfile, - struct gengetopt_args_info *args_info); - -/** - * Save the contents of the option struct into a (text) file. - * This file can be read by the config file parser (if generated by gengetopt) - * @param filename the file where to save - * @param args_info the option struct to save - * @return 0 if everything went fine, NON 0 if an error took place - */ -int cmdline_parser_file_save(const char *filename, - struct gengetopt_args_info *args_info); - -/** - * Print the help - */ -void cmdline_parser_print_help(void); -/** - * Print the version - */ -void cmdline_parser_print_version(void); - -/** - * Initializes all the fields a cmdline_parser_params structure - * to their default values - * @param params the structure to initialize - */ -void cmdline_parser_params_init(struct cmdline_parser_params *params); - -/** - * Allocates dynamically a cmdline_parser_params structure and initializes - * all its fields to their default values - * @return the created and initialized cmdline_parser_params structure - */ -struct cmdline_parser_params *cmdline_parser_params_create(void); - -/** - * Initializes the passed gengetopt_args_info structure's fields - * (also set default values for options that have a default) - * @param args_info the structure to initialize - */ -void cmdline_parser_init (struct gengetopt_args_info *args_info); -/** - * Deallocates the string fields of the gengetopt_args_info structure - * (but does not deallocate the structure itself) - * @param args_info the structure to deallocate - */ -void cmdline_parser_free (struct gengetopt_args_info *args_info); - -/** - * Checks that all the required options were specified - * @param args_info the structure to check - * @param prog_name the name of the program that will be used to print - * possible errors - * @return - */ -int cmdline_parser_required (struct gengetopt_args_info *args_info, - const char *prog_name); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ -#endif /* CMDLINE_H */ diff --git a/main_mpd.c b/main_mpd.c deleted file mode 100644 index fc41cb3..0000000 --- a/main_mpd.c +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include - -#include "analysis.h" -#include "cmdline.h" -#include "constants.h" -#include "utilities.h" - -// TODO: Handle deletions from db - -// IDLE loop control variable -volatile bool mpd_run_idle_loop = true; -// MPD connection handler -struct mpd_connection *conn; - -/** - * Handle interruption when waiting for MPD IDLE items. - */ -void sigint_catch_function(int signo) -{ - // TODO: Not working - // TODO: Should store latest seen mtime there - printf("Exiting...\n"); - - // Stop listening for MPD IDLE - mpd_run_noidle(conn); - - // Stop main loop - mpd_run_idle_loop = false; -} - - -/** - * Update the database. - * - * @param mpd_connection MPD connection object to use. - * @param initial_mtime Initial mtime to use. - * @param mpd_base_path Root directory of the MPD library. - * @param mpdbliss_data_db Path to the db to use. - */ -long int update_database( - time_t initial_mtime, - const char *mpd_base_path, - const char* mpdbliss_data_db - ) -{ - // Store latest mtime seen - time_t latest_mtime = initial_mtime; - - // Get number of songs in db - struct mpd_stats* stats = mpd_run_stats(conn); - if (NULL == stats) { - fprintf(stderr, "Unable to fetch number of songs in the db.\n"); - return -1; - } - unsigned int n_songs = mpd_stats_get_number_of_songs(stats); - if (0 == n_songs) { - fprintf(stderr, "Unable to fetch number of songs in the db.\n"); - return -1; - } - - // Get the list of all the files to process - if (!mpd_send_list_all_meta(conn, NULL)) { - fprintf(stderr, "Unable to get a full list of items in the db.\n"); - return -1; - } - - // Connect to SQLite db - sqlite3 *dbh; - if (0 != sqlite3_open(mpdbliss_data_db, &dbh)) { - fprintf(stderr, "Unable to open SQLite db.\n"); - return -1; - } - int dberr = sqlite3_exec(dbh, "PRAGMA foreign_keys = ON", NULL, NULL, NULL); - if (SQLITE_OK != dberr) { - fprintf(stderr, "Unable to open SQLite db.\n"); - sqlite3_close(dbh); - exit(EXIT_FAILURE); - } - - // Retrieve the received list in memory, to prevent timeout - struct mpd_entity **entities = malloc(sizeof(struct mpd_entity *) * n_songs); - struct mpd_entity *entity; - int i = 0; - while ((entity = mpd_recv_entity(conn)) != NULL) { - switch (mpd_entity_get_type(entity)) { - case MPD_ENTITY_TYPE_SONG: - entities[i] = entity; - break; - - case MPD_ENTITY_TYPE_UNKNOWN: - case MPD_ENTITY_TYPE_DIRECTORY: - case MPD_ENTITY_TYPE_PLAYLIST: - // Pass such types - mpd_entity_free(entity); - continue; - } - ++i; - } - - // Process all the entities - for (int i = 0; i < n_songs; ++i) { - struct mpd_entity *entity = entities[i]; - const struct mpd_song *song = mpd_entity_get_song(entity); - - // Pass song if already seen - time_t song_mtime = mpd_song_get_last_modified(song); - if (difftime(song_mtime, initial_mtime) <= 0) { - mpd_entity_free(entity); - continue; - } - - // Compute bl_analyze and store it - const char *song_uri = mpd_song_get_uri(song); - if (1 == _parse_music_helper(dbh, mpd_base_path, song_uri)) { - mpd_entity_free(entity); - continue; - } - - // Update latest mtime - if (difftime(song_mtime, latest_mtime) >= 0) { - latest_mtime = song_mtime; - } - - // Free the allocated entity - mpd_entity_free(entity); - printf("\n"); - } - - // Close SQLite connection - sqlite3_close(dbh); - - // Check if exit was due to an error - if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { - printf("MPD Error: %s\n", mpd_connection_get_error_message(conn)); - return -1; - } - - free(entities); - printf("Done! :)\n"); - - // Return last_mtime, if no error occured. - return latest_mtime; -} - - -int main(int argc, char** argv) { - // Scan arguments - struct gengetopt_args_info args_info; - if (0 != cmdline_parser(argc, argv, &args_info)) { - exit(EXIT_FAILURE) ; - } - - // Create MPD connection - char *mpd_host = NULL; - if (strlen(args_info.host_arg) > 0) { - mpd_host = args_info.host_arg; - } - struct mpd_settings* conn_settings = mpd_settings_new( - mpd_host, - args_info.port_arg, - 0, - NULL, - NULL); - // Connect - conn = mpd_connection_new( - mpd_settings_get_host(conn_settings), - mpd_settings_get_port(conn_settings), - mpd_settings_get_timeout_ms(conn_settings)); - if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) { - fprintf(stderr, "Unable to connect to the MPD server.\n"); - exit(EXIT_FAILURE); - } - // Handle passwords - const char* mpd_password = mpd_settings_get_password(conn_settings); - if (NULL != mpd_password) { - if (!mpd_run_password(conn, mpd_password)) { - fprintf(stderr, "Unable to send password to the MPD server.\n"); - exit(EXIT_FAILURE); - } - } - - // Handle mpd_root argument - char mpd_base_path[DEFAULT_STRING_LENGTH + 1] = ""; - strncat(mpd_base_path, args_info.mpd_root_arg, DEFAULT_STRING_LENGTH); - strip_trailing_slash(mpd_base_path); - strncat(mpd_base_path, "/", DEFAULT_STRING_LENGTH - strlen(mpd_base_path)); - - // Get data directory, init db file - char mpdbliss_data_folder[DEFAULT_STRING_LENGTH + 1] = ""; - char mpdbliss_data_db[DEFAULT_STRING_LENGTH + 1] = ""; - if (0 != _init_db(mpdbliss_data_folder, mpdbliss_data_db)) { - exit(EXIT_FAILURE); - } - - // Set data file path - char mpdbliss_data_file[DEFAULT_STRING_LENGTH + 1] = ""; - strncat(mpdbliss_data_file, mpdbliss_data_folder, DEFAULT_STRING_LENGTH); - strncat(mpdbliss_data_file, "/latest_mtime.txt", DEFAULT_STRING_LENGTH - strlen(mpdbliss_data_file)); - - // Get latest mtime - time_t last_mtime = 0; // Set it to epoch by default - FILE *fp = fopen(mpdbliss_data_file, "r"); - if (NULL != fp) { - // Read it from file if applicable - fscanf(fp, "%ld\n", &last_mtime); - fclose(fp); - } - - // Purge db if a rescan is needed - if (1 == args_info.rescan_flag) { - if (0 != _purge_db(mpdbliss_data_db)) { - exit(EXIT_FAILURE); - } - // Set last_mtime to 0 - last_mtime = 0; - } - - // Check if a full rescan is needed - if (1 == args_info.rescan_flag) { - last_mtime = update_database(last_mtime, mpd_base_path, mpdbliss_data_db); - if (last_mtime < 0) { - fprintf(stderr, "An error occurred while scanning library.\n"); - exit(EXIT_FAILURE); - } - } - // Else, if we want to rescan errored files - else if (1 == args_info.rescan_errors_flag) { - // Update last_mtime - _rescan_errored(mpdbliss_data_db, mpd_base_path); - } - // Else, if we requested an update of the db - else if (true == args_info.update_flag) { - // Rescan from last known mtime - last_mtime = update_database(last_mtime, mpd_base_path, mpdbliss_data_db); - if (last_mtime < 0) { - fprintf(stderr, "An error occurred while scanning library.\n"); - exit(EXIT_FAILURE); - } - } - else { - // Setting signal handler - if (signal(SIGINT, sigint_catch_function) == SIG_ERR) { - fprintf(stderr, "An error occurred while setting a signal handler.\n"); - exit(EXIT_FAILURE); - } - - while (mpd_run_idle_loop) { - // Else, start an MPD IDLE connection - mpd_run_idle_mask(conn, MPD_IDLE_DATABASE); - - // Rescan from last known mtime - last_mtime = update_database(last_mtime, mpd_base_path, mpdbliss_data_db); - if (last_mtime < 0) { - fprintf(stderr, "An error occurred while scanning library.\n"); - exit(EXIT_FAILURE); - } - - // Stop listening to MPD IDLE - mpd_run_noidle(conn); - } - } - - // Write last_mtime - fp = fopen(mpdbliss_data_file, "w+"); - if (NULL != fp) { - fprintf(fp, "%ld\n", last_mtime); - fclose(fp); - } - else { - fprintf(stderr, "Unable to store latest mtime seen.\n"); - exit(EXIT_FAILURE); - } - - return EXIT_SUCCESS; -} diff --git a/client/client.py b/mpd/client.py similarity index 97% rename from client/client.py rename to mpd/client.py index c1be99a..d7fd138 100755 --- a/client/client.py +++ b/mpd/client.py @@ -19,6 +19,8 @@ import sys from mpd import MPDClient +# TODO: Timeout + logging.basicConfig(level=logging.INFO) _QUEUE_LENGTH = 20 @@ -26,9 +28,9 @@ _DISTANCE_THRESHOLD = 4.0 _SIMILARITY_THRESHOLD = 0.95 if "XDG_DATA_HOME" in os.environ: - _MPDBLISS_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/mpdbliss") + _BLISSIFY_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/blissify") else: - _MPDBLISS_DATA_HOME = os.path.expanduser("~/.local/share/mpdbliss") + _BLISSIFY_DATA_HOME = os.path.expanduser("~/.local/share/blissify") def main(queue_length): @@ -50,7 +52,7 @@ def main(queue_length): if mpd_password is not None: client.password(mpd_password) # Connect to db - db_path = os.path.join(_MPDBLISS_DATA_HOME, "db.sqlite3") + db_path = os.path.join(_BLISSIFY_DATA_HOME, "db.sqlite3") logging.debug("Using DB path: %s." % (db_path,)) conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row diff --git a/mpd/requirements.txt b/mpd/requirements.txt new file mode 100644 index 0000000..0f08daa --- /dev/null +++ b/mpd/requirements.txt @@ -0,0 +1 @@ +python-dateutil diff --git a/mpd/server.py b/mpd/server.py new file mode 100755 index 0000000..63e9195 --- /dev/null +++ b/mpd/server.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +""" +This is a script to build the necessary database from a MPD music library. + +Run `python3 server.py --help` for more infos on how to use. +""" +import argparse +import dateutil.parser +import os +import sqlite3 +import subprocess + +from mpd import MPDClient + +if "XDG_DATA_HOME" in os.environ: + _BLISSIFY_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/blissify") +else: + _BLISSIFY_DATA_HOME = os.path.expanduser("~/.local/share/blissify") + + +def init_connection(): + """ + Returns an MPDClient connection. + """ + # Get MPD connection settings + try: + mpd_host = os.environ["MPD_HOST"] + mpd_password, mpd_host = mpd_host.split("@") + except KeyError: + mpd_host = "localhost" + mpd_password = None + try: + mpd_port = os.environ["MPD_PORT"] + except KeyError: + mpd_port = 6600 + + # Connect to MPD² + client = MPDClient() + client.connect(mpd_host, mpd_port) + if mpd_password is not None: + client.password(mpd_password) + return client + + +def close_connection(client): + """ + Closes an MPDClient connection. + """ + client.close() + client.disconnect() + + +def full_rescan(mpd_root): + """ + Perform a full rescan of the MPD library. + """ + client = init_connection() + # Get all songs from MPD and Blissify them + all_songs = [x["file"] for x in client.listall() if "file" in x] + subprocess.check_call(["blissify", mpd_root] + all_songs) + # Update the latest mtime stored + with open(os.path.join(_BLISSIFY_DATA_HOME, "latest_mtime.txt"), "r") as fh: + latest_mtime = int(fh.read()) + for song in all_songs: + last_modified = client.find("file", song)["last_modified"] + last_modified = int(dateutil.parser.parse(last_modified).timestamp()) + if last_modified > latest_mtime: + latest_mtime = last_modified + with open(os.path.join(_BLISSIFY_DATA_HOME, "latest_mtime.txt"), "w") as fh: + fh.write(latest_mtime) + close_connection(client) + + +def rescan_errored(mpd_root): + """ + Rescan only errored files. + """ + # Connect to db + db_path = os.path.join(_BLISSIFY_DATA_HOME, "db.sqlite3") + logging.debug("Using DB path: %s." % (db_path,)) + conn = sqlite3.connect(db_path) + conn.row_factory = sqlite3.Row + conn.execute('pragma foreign_keys=ON') + cur = conn.cursor() + # Get errored files + cur.execute("SELECT filename FROM errors") + errors = cur.fetchall() + # Rerun blissify on them + if errors is not None: + subprocess.check_call(["blissify", mpd_root] + errors) + + +def update_db(mpd_root): + """ + Update the blissify db taking newly added songs in MPD library. + """ + client = init_connection() + with open(os.path.join(_BLISSIFY_DATA_HOME, "latest_mtime.txt"), "r") as fh: + latest_mtime = int(fh.read()) + songs = [x["file"] for x in client.find("modified-since", latest_mtime)] + subprocess.check_call(["blissify", mpd_root] + songs) + # Update the latest mtime stored + with open(os.path.join(_BLISSIFY_DATA_HOME, "latest_mtime.txt"), "r") as fh: + latest_mtime = int(fh.read()) + for song in songs: + last_modified = client.find("file", song)["last_modified"] + last_modified = int(dateutil.parser.parse(last_modified).timestamp()) + if last_modified > latest_mtime: + latest_mtime = last_modified + with open(os.path.join(_BLISSIFY_DATA_HOME, "latest_mtime.txt"), "w") as fh: + fh.write(latest_mtime) + close_connection(client) + + +def listen(mpd_root): + """ + Listen for additions in MPD library using MPD IDLE and handle them + immediately. + """ + client = init_connection() + while True: + try: + client.idle("database") + except KeyboardInterrupt: + break + update_db(mpd_root) + close_connection(client) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("mpd_root", help="Root folder of your MPD library.") + + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("--full-rescan", help="Scan the whole library.", + action="store_true", default=False) + group.add_argument("--rescan-errored", help="Rescan errored files.", + action="store_true", default=False) + group.add_argument("--update", + help="Update the database with new files in the library", + action="store_true", default=False) + group.add_argument("--listen", + help="Listen for MPD IDLE signals to do live scanning.", + action="store_true", default=False) + + args = parser.parse_args() + + if args.full_rescan: + full_rescan(args.mpd_root) + elif args.rescan_errored: + rescan_errored(args.mpd_root) + elif args.update: + update_db(args.mpd_root) + elif args.listen: + listen(args.mpd_root) + else: + sys.exit() diff --git a/client/build_cache.py b/scripts/build_cache.py similarity index 94% rename from client/build_cache.py rename to scripts/build_cache.py index dcffc10..1456bdb 100755 --- a/client/build_cache.py +++ b/scripts/build_cache.py @@ -7,13 +7,13 @@ import sqlite3 logging.basicConfig(level=logging.DEBUG) if "XDG_DATA_HOME" in os.environ: - _MPDBLISS_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/mpdbliss") + _BLISSIFY_DATA_HOME = os.path.expandvars("$XDG_DATA_HOME/blissify") else: - _MPDBLISS_DATA_HOME = os.path.expanduser("~/.local/share/mpdbliss") + _BLISSIFY_DATA_HOME = os.path.expanduser("~/.local/share/blissify") def main(): - db_path = os.path.join(_MPDBLISS_DATA_HOME, "db.sqlite3") + db_path = os.path.join(_BLISSIFY_DATA_HOME, "db.sqlite3") logging.debug("Using DB path: %s." % (db_path,)) conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row diff --git a/src/analysis.c b/src/analysis.c index 86c9a91..ff79bdf 100644 --- a/src/analysis.c +++ b/src/analysis.c @@ -19,12 +19,12 @@ int _init_db(char *data_folder, char* db_path) if (NULL == xdg_data_home_env) { strncat(data_folder, getenv("HOME"), DEFAULT_STRING_LENGTH); strip_trailing_slash(data_folder); - strncat(data_folder, "/.local/share/mpdbliss", DEFAULT_STRING_LENGTH - strlen(data_folder)); + strncat(data_folder, "/.local/share/blissify", DEFAULT_STRING_LENGTH - strlen(data_folder)); } else { strncat(data_folder, xdg_data_home_env, DEFAULT_STRING_LENGTH); strip_trailing_slash(data_folder); - strncat(data_folder, "/mpdbliss", DEFAULT_STRING_LENGTH - strlen(data_folder)); + strncat(data_folder, "/blissify", DEFAULT_STRING_LENGTH - strlen(data_folder)); } // Ensure data folder exists diff --git a/src/args.ggo b/src/args.ggo deleted file mode 100644 index 116682a..0000000 --- a/src/args.ggo +++ /dev/null @@ -1,10 +0,0 @@ -package "MPDBliss" -version "VERSION" -purpose "Binding MPD and Bliss." - -option "rescan" r "Rescan the whole MPD database." flag off -option "rescan-errors" e "Rescan the errored files from the MPD database." flag off -option "update" u "Trigger an update." flag off -option "mpd_root" - "MPD library base path." string -option "host" - "MPD host." string default="" optional -option "port" - "MPD port." int default="0" optional diff --git a/src/cmdline.c b/src/cmdline.c deleted file mode 100644 index de41202..0000000 --- a/src/cmdline.c +++ /dev/null @@ -1,658 +0,0 @@ -/* - File autogenerated by gengetopt version 2.22.6 - generated with the following command: - gengetopt - - The developers of gengetopt consider the fixed text that goes in all - gengetopt output files to be in the public domain: - we make no copyright claims on it. -*/ - -/* If we use autoconf. */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#ifndef FIX_UNUSED -#define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ -#endif - -#include - -#include "cmdline.h" - -const char *gengetopt_args_info_purpose = "Binding MPD and Bliss."; - -const char *gengetopt_args_info_usage = "Usage: MPDBliss [OPTIONS]..."; - -const char *gengetopt_args_info_versiontext = ""; - -const char *gengetopt_args_info_description = ""; - -const char *gengetopt_args_info_help[] = { - " -h, --help Print help and exit", - " -V, --version Print version and exit", - " -r, --rescan Rescan the whole MPD database. (default=off)", - " -e, --rescan-errors Rescan the errored files from the MPD database.\n (default=off)", - " -u, --update Trigger an update. (default=off)", - " --mpd_root=STRING MPD library base path.", - " --host=STRING MPD host. (default=`')", - " --port=INT MPD port. (default=`0')", - 0 -}; - -typedef enum {ARG_NO - , ARG_FLAG - , ARG_STRING - , ARG_INT -} cmdline_parser_arg_type; - -static -void clear_given (struct gengetopt_args_info *args_info); -static -void clear_args (struct gengetopt_args_info *args_info); - -static int -cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params, const char *additional_error); - -static int -cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); - -static char * -gengetopt_strdup (const char *s); - -static -void clear_given (struct gengetopt_args_info *args_info) -{ - args_info->help_given = 0 ; - args_info->version_given = 0 ; - args_info->rescan_given = 0 ; - args_info->rescan_errors_given = 0 ; - args_info->update_given = 0 ; - args_info->mpd_root_given = 0 ; - args_info->host_given = 0 ; - args_info->port_given = 0 ; -} - -static -void clear_args (struct gengetopt_args_info *args_info) -{ - FIX_UNUSED (args_info); - args_info->rescan_flag = 0; - args_info->rescan_errors_flag = 0; - args_info->update_flag = 0; - args_info->mpd_root_arg = NULL; - args_info->mpd_root_orig = NULL; - args_info->host_arg = gengetopt_strdup (""); - args_info->host_orig = NULL; - args_info->port_arg = 0; - args_info->port_orig = NULL; - -} - -static -void init_args_info(struct gengetopt_args_info *args_info) -{ - - - args_info->help_help = gengetopt_args_info_help[0] ; - args_info->version_help = gengetopt_args_info_help[1] ; - args_info->rescan_help = gengetopt_args_info_help[2] ; - args_info->rescan_errors_help = gengetopt_args_info_help[3] ; - args_info->update_help = gengetopt_args_info_help[4] ; - args_info->mpd_root_help = gengetopt_args_info_help[5] ; - args_info->host_help = gengetopt_args_info_help[6] ; - args_info->port_help = gengetopt_args_info_help[7] ; - -} - -void -cmdline_parser_print_version (void) -{ - printf ("%s %s\n", - (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), - CMDLINE_PARSER_VERSION); - - if (strlen(gengetopt_args_info_versiontext) > 0) - printf("\n%s\n", gengetopt_args_info_versiontext); -} - -static void print_help_common(void) { - cmdline_parser_print_version (); - - if (strlen(gengetopt_args_info_purpose) > 0) - printf("\n%s\n", gengetopt_args_info_purpose); - - if (strlen(gengetopt_args_info_usage) > 0) - printf("\n%s\n", gengetopt_args_info_usage); - - printf("\n"); - - if (strlen(gengetopt_args_info_description) > 0) - printf("%s\n\n", gengetopt_args_info_description); -} - -void -cmdline_parser_print_help (void) -{ - int i = 0; - print_help_common(); - while (gengetopt_args_info_help[i]) - printf("%s\n", gengetopt_args_info_help[i++]); -} - -void -cmdline_parser_init (struct gengetopt_args_info *args_info) -{ - clear_given (args_info); - clear_args (args_info); - init_args_info (args_info); -} - -void -cmdline_parser_params_init(struct cmdline_parser_params *params) -{ - if (params) - { - params->override = 0; - params->initialize = 1; - params->check_required = 1; - params->check_ambiguity = 0; - params->print_errors = 1; - } -} - -struct cmdline_parser_params * -cmdline_parser_params_create(void) -{ - struct cmdline_parser_params *params = - (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); - cmdline_parser_params_init(params); - return params; -} - -static void -free_string_field (char **s) -{ - if (*s) - { - free (*s); - *s = 0; - } -} - - -static void -cmdline_parser_release (struct gengetopt_args_info *args_info) -{ - - free_string_field (&(args_info->mpd_root_arg)); - free_string_field (&(args_info->mpd_root_orig)); - free_string_field (&(args_info->host_arg)); - free_string_field (&(args_info->host_orig)); - free_string_field (&(args_info->port_orig)); - - - - clear_given (args_info); -} - - -static void -write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) -{ - FIX_UNUSED (values); - if (arg) { - fprintf(outfile, "%s=\"%s\"\n", opt, arg); - } else { - fprintf(outfile, "%s\n", opt); - } -} - - -int -cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) -{ - int i = 0; - - if (!outfile) - { - fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); - return EXIT_FAILURE; - } - - if (args_info->help_given) - write_into_file(outfile, "help", 0, 0 ); - if (args_info->version_given) - write_into_file(outfile, "version", 0, 0 ); - if (args_info->rescan_given) - write_into_file(outfile, "rescan", 0, 0 ); - if (args_info->rescan_errors_given) - write_into_file(outfile, "rescan-errors", 0, 0 ); - if (args_info->update_given) - write_into_file(outfile, "update", 0, 0 ); - if (args_info->mpd_root_given) - write_into_file(outfile, "mpd_root", args_info->mpd_root_orig, 0); - if (args_info->host_given) - write_into_file(outfile, "host", args_info->host_orig, 0); - if (args_info->port_given) - write_into_file(outfile, "port", args_info->port_orig, 0); - - - i = EXIT_SUCCESS; - return i; -} - -int -cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) -{ - FILE *outfile; - int i = 0; - - outfile = fopen(filename, "w"); - - if (!outfile) - { - fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); - return EXIT_FAILURE; - } - - i = cmdline_parser_dump(outfile, args_info); - fclose (outfile); - - return i; -} - -void -cmdline_parser_free (struct gengetopt_args_info *args_info) -{ - cmdline_parser_release (args_info); -} - -/** @brief replacement of strdup, which is not standard */ -char * -gengetopt_strdup (const char *s) -{ - char *result = 0; - if (!s) - return result; - - result = (char*)malloc(strlen(s) + 1); - if (result == (char*)0) - return (char*)0; - strcpy(result, s); - return result; -} - -int -cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) -{ - return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); -} - -int -cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params) -{ - int result; - result = cmdline_parser_internal (argc, argv, args_info, params, 0); - - if (result == EXIT_FAILURE) - { - cmdline_parser_free (args_info); - exit (EXIT_FAILURE); - } - - return result; -} - -int -cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) -{ - int result; - struct cmdline_parser_params params; - - params.override = override; - params.initialize = initialize; - params.check_required = check_required; - params.check_ambiguity = 0; - params.print_errors = 1; - - result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); - - if (result == EXIT_FAILURE) - { - cmdline_parser_free (args_info); - exit (EXIT_FAILURE); - } - - return result; -} - -int -cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) -{ - int result = EXIT_SUCCESS; - - if (cmdline_parser_required2(args_info, prog_name, 0) > 0) - result = EXIT_FAILURE; - - if (result == EXIT_FAILURE) - { - cmdline_parser_free (args_info); - exit (EXIT_FAILURE); - } - - return result; -} - -int -cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) -{ - int error_occurred = 0; - FIX_UNUSED (additional_error); - - /* checks for required options */ - if (! args_info->mpd_root_given) - { - fprintf (stderr, "%s: '--mpd_root' option required%s\n", prog_name, (additional_error ? additional_error : "")); - error_occurred = 1; - } - - - /* checks for dependences among options */ - - return error_occurred; -} - - -static char *package_name = 0; - -/** - * @brief updates an option - * @param field the generic pointer to the field to update - * @param orig_field the pointer to the orig field - * @param field_given the pointer to the number of occurrence of this option - * @param prev_given the pointer to the number of occurrence already seen - * @param value the argument for this option (if null no arg was specified) - * @param possible_values the possible values for this option (if specified) - * @param default_value the default value (in case the option only accepts fixed values) - * @param arg_type the type of this option - * @param check_ambiguity @see cmdline_parser_params.check_ambiguity - * @param override @see cmdline_parser_params.override - * @param no_free whether to free a possible previous value - * @param multiple_option whether this is a multiple option - * @param long_opt the corresponding long option - * @param short_opt the corresponding short option (or '-' if none) - * @param additional_error possible further error specification - */ -static -int update_arg(void *field, char **orig_field, - unsigned int *field_given, unsigned int *prev_given, - char *value, const char *possible_values[], - const char *default_value, - cmdline_parser_arg_type arg_type, - int check_ambiguity, int override, - int no_free, int multiple_option, - const char *long_opt, char short_opt, - const char *additional_error) -{ - char *stop_char = 0; - const char *val = value; - int found; - char **string_field; - FIX_UNUSED (field); - - stop_char = 0; - found = 0; - - if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) - { - if (short_opt != '-') - fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", - package_name, long_opt, short_opt, - (additional_error ? additional_error : "")); - else - fprintf (stderr, "%s: `--%s' option given more than once%s\n", - package_name, long_opt, - (additional_error ? additional_error : "")); - return 1; /* failure */ - } - - FIX_UNUSED (default_value); - - if (field_given && *field_given && ! override) - return 0; - if (prev_given) - (*prev_given)++; - if (field_given) - (*field_given)++; - if (possible_values) - val = possible_values[found]; - - switch(arg_type) { - case ARG_FLAG: - *((int *)field) = !*((int *)field); - break; - case ARG_INT: - if (val) *((int *)field) = strtol (val, &stop_char, 0); - break; - case ARG_STRING: - if (val) { - string_field = (char **)field; - if (!no_free && *string_field) - free (*string_field); /* free previous string */ - *string_field = gengetopt_strdup (val); - } - break; - default: - break; - }; - - /* check numeric conversion */ - switch(arg_type) { - case ARG_INT: - if (val && !(stop_char && *stop_char == '\0')) { - fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); - return 1; /* failure */ - } - break; - default: - ; - }; - - /* store the original value */ - switch(arg_type) { - case ARG_NO: - case ARG_FLAG: - break; - default: - if (value && orig_field) { - if (no_free) { - *orig_field = value; - } else { - if (*orig_field) - free (*orig_field); /* free previous string */ - *orig_field = gengetopt_strdup (value); - } - } - }; - - return 0; /* OK */ -} - - -int -cmdline_parser_internal ( - int argc, char **argv, struct gengetopt_args_info *args_info, - struct cmdline_parser_params *params, const char *additional_error) -{ - int c; /* Character of the parsed option. */ - - int error_occurred = 0; - struct gengetopt_args_info local_args_info; - - int override; - int initialize; - int check_required; - int check_ambiguity; - - package_name = argv[0]; - - override = params->override; - initialize = params->initialize; - check_required = params->check_required; - check_ambiguity = params->check_ambiguity; - - if (initialize) - cmdline_parser_init (args_info); - - cmdline_parser_init (&local_args_info); - - optarg = 0; - optind = 0; - opterr = params->print_errors; - optopt = '?'; - - while (1) - { - int option_index = 0; - - static struct option long_options[] = { - { "help", 0, NULL, 'h' }, - { "version", 0, NULL, 'V' }, - { "rescan", 0, NULL, 'r' }, - { "rescan-errors", 0, NULL, 'e' }, - { "update", 0, NULL, 'u' }, - { "mpd_root", 1, NULL, 0 }, - { "host", 1, NULL, 0 }, - { "port", 1, NULL, 0 }, - { 0, 0, 0, 0 } - }; - - c = getopt_long (argc, argv, "hVreu", long_options, &option_index); - - if (c == -1) break; /* Exit from `while (1)' loop. */ - - switch (c) - { - case 'h': /* Print help and exit. */ - cmdline_parser_print_help (); - cmdline_parser_free (&local_args_info); - exit (EXIT_SUCCESS); - - case 'V': /* Print version and exit. */ - cmdline_parser_print_version (); - cmdline_parser_free (&local_args_info); - exit (EXIT_SUCCESS); - - case 'r': /* Rescan the whole MPD database.. */ - - - if (update_arg((void *)&(args_info->rescan_flag), 0, &(args_info->rescan_given), - &(local_args_info.rescan_given), optarg, 0, 0, ARG_FLAG, - check_ambiguity, override, 1, 0, "rescan", 'r', - additional_error)) - goto failure; - - break; - case 'e': /* Rescan the errored files from the MPD database.. */ - - - if (update_arg((void *)&(args_info->rescan_errors_flag), 0, &(args_info->rescan_errors_given), - &(local_args_info.rescan_errors_given), optarg, 0, 0, ARG_FLAG, - check_ambiguity, override, 1, 0, "rescan-errors", 'e', - additional_error)) - goto failure; - - break; - case 'u': /* Trigger an update.. */ - - - if (update_arg((void *)&(args_info->update_flag), 0, &(args_info->update_given), - &(local_args_info.update_given), optarg, 0, 0, ARG_FLAG, - check_ambiguity, override, 1, 0, "update", 'u', - additional_error)) - goto failure; - - break; - - case 0: /* Long option with no short option */ - /* MPD library base path.. */ - if (strcmp (long_options[option_index].name, "mpd_root") == 0) - { - - - if (update_arg( (void *)&(args_info->mpd_root_arg), - &(args_info->mpd_root_orig), &(args_info->mpd_root_given), - &(local_args_info.mpd_root_given), optarg, 0, 0, ARG_STRING, - check_ambiguity, override, 0, 0, - "mpd_root", '-', - additional_error)) - goto failure; - - } - /* MPD host.. */ - else if (strcmp (long_options[option_index].name, "host") == 0) - { - - - if (update_arg( (void *)&(args_info->host_arg), - &(args_info->host_orig), &(args_info->host_given), - &(local_args_info.host_given), optarg, 0, "", ARG_STRING, - check_ambiguity, override, 0, 0, - "host", '-', - additional_error)) - goto failure; - - } - /* MPD port.. */ - else if (strcmp (long_options[option_index].name, "port") == 0) - { - - - if (update_arg( (void *)&(args_info->port_arg), - &(args_info->port_orig), &(args_info->port_given), - &(local_args_info.port_given), optarg, 0, "0", ARG_INT, - check_ambiguity, override, 0, 0, - "port", '-', - additional_error)) - goto failure; - - } - - break; - case '?': /* Invalid option. */ - /* `getopt_long' already printed an error message. */ - goto failure; - - default: /* bug: option not considered. */ - fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); - abort (); - } /* switch */ - } /* while */ - - - - if (check_required) - { - error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error); - } - - cmdline_parser_release (&local_args_info); - - if ( error_occurred ) - return (EXIT_FAILURE); - - return 0; - -failure: - - cmdline_parser_release (&local_args_info); - return (EXIT_FAILURE); -} diff --git a/main_args.c b/src/main.c similarity index 80% rename from main_args.c rename to src/main.c index c65afd8..6dc7940 100644 --- a/main_args.c +++ b/src/main.c @@ -18,9 +18,9 @@ int main(int argc, char** argv) { } // Get data directory, init db file - char mpdbliss_data_folder[DEFAULT_STRING_LENGTH + 1] = ""; - char mpdbliss_data_db[DEFAULT_STRING_LENGTH + 1] = ""; - if (0 != _init_db(mpdbliss_data_folder, mpdbliss_data_db)) { + char blissify_data_folder[DEFAULT_STRING_LENGTH + 1] = ""; + char blissify_data_db[DEFAULT_STRING_LENGTH + 1] = ""; + if (0 != _init_db(blissify_data_folder, blissify_data_db)) { exit(EXIT_FAILURE); } @@ -28,7 +28,7 @@ int main(int argc, char** argv) { // Connect to SQLite db sqlite3 *dbh; - if (0 != sqlite3_open(mpdbliss_data_db, &dbh)) { + if (0 != sqlite3_open(blissify_data_db, &dbh)) { fprintf(stderr, "Unable to open SQLite db.\n"); exit(EXIT_FAILURE); }