Logo Search packages:      
Sourcecode: easyh10 version File versions  Download package

main.c

/*
 *      main
 *
 *      Copyright (c) 2005 Nyaochi
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
 * http://www.gnu.org/copyleft/gpl.html .
 *
 */

/* $Id: main.c,v 1.78.2.2 2005/11/14 12:48:50 nyaochi Exp $ */

#ifdef      HAVE_CONFIG_H
#include <config.h>
#endif/*HAVE_CONFIG_H*/

#ifdef      _MSC_VER
#include <direct.h>           /* getcwd() */
#endif/*_MSC_VER*/

#include <os.h>
#include <limits.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ucs2char.h>

#include <filepathutil.h>
#include <easyh10.h>

#ifdef      HAVE_GETOPT_H
#include <getopt.h>
#else
#include "getopt.h"
#endif

#define     APPLICATION_S     "EasyH10 [CUI]"
#define     VERSION_S         "1.2.1"
#define     COPYRIGHT_S       "Copyright (c) 2005 by Nyaochi"

#ifndef           _WIN32
#define     MBS_CHARSET "UTF-8"
#endif

static int verbose = 0;

enum {
      MODE_NONE =             0,
      MODE_DATABASE =         0x00000001,
      MODE_TEMPLATE =         0x00000002,
      MODE_INSTALL =          0x00000004,
      MODE_PLAYLIST =         0x00000008,
      MODE_DUMP =             0x00000010,
      MODE_HELP =             0x00000020,
      MODE_VERSION =          0x00000040,
};

void usage(FILE *fp, const char *argv0)
{
      fprintf(fp, "USAGE: %s [OPTIONS] [LOCATION]\n", argv0);
#ifdef      _WIN32
      fprintf(fp, "  LOCATION      Absolute path to the H10 root directory (e.g., D:\\)\n");
#else
      fprintf(fp, "  LOCATION      Absolute path to the H10 root directory (e.g., /mnt/usbdisk/)\n");
#endif
      fprintf(fp, "\n");

      fprintf(fp, "Database construction options:\n");
      fprintf(fp, "  -C, --construct       Construct a media database from music files\n");
      fprintf(fp, "  -i, --incremental     Enable incremental update mode\n");
      fprintf(fp, "  -c, --clean           Clean unused database entries in the existing database\n");
      fprintf(fp, "  -U, --update          Update a media database (alias of options \"-Cic\")\n");
      fprintf(fp, "  -n, --new             Discard the existing database and rebuild a new one\n");
      fprintf(fp, "  -o, --order=TYPE      Specify a playback order:\n");
      fprintf(fp, "          d, default        Leave an H10 firmware for playback order (DEFAULT)\n");
      fprintf(fp, "          t, tracktitle     Force an alphabetical order of track titles\n");
      fprintf(fp, "          f, filename       Force an alphabetical order of file names\n");
      fprintf(fp, "          n, tracknumber    Force a numerical order of track numbers\n");
      fprintf(fp, "          c, complete       Force a complete random order (always shuffle)\n");
      fprintf(fp, "          a, album          Force a random order when playing an album\n");
      fprintf(fp, "          l, all            Force a random order when playing all titles\n");
      fprintf(fp, "  -z, --source=METHOD   Specify a method for obtaining media information:\n");
      fprintf(fp, "          m                 Tag information in music files (DEFAULT)\n");
      fprintf(fp, "          [g]p              Parse pathnames to obtain (genres and) artists\n");
      fprintf(fp, "          [g]pa             Parse pathnames to obtain (genres,) artists, albums\n");
      fprintf(fp, "          [g]pa[n]t         Parse pathnames to obtain (genres,) artists, albums\n");
      fprintf(fp, "                            and parse filenames to obtain (numbers and) titles\n");
      fprintf(fp, "\n");
      fprintf(fp, "Playlist conversion options:\n");
      fprintf(fp, "  -P, --playlist        Convert playlist files in PLAYLIST directory\n");
      fprintf(fp, "  -M, --music           Convert playlist files in MUSIC directories\n");
      fprintf(fp, "  -r, --reconvert       Discard the existing PLP/PLA playlist and reconvert\n");
      fprintf(fp, "  -g, --guess-missing   Guess pathnames of missing music files in a playlist\n");
      fprintf(fp, "  -f, --find-missing    Find pathnames of missing music files in a playlist\n");
      fprintf(fp, "  -k, --skip-missing    Skip missing music files in a playlist and continue\n");
      fprintf(fp, "\n");
      fprintf(fp, "H10 player model options:\n");
      fprintf(fp, "  -t, --model=MODEL     Apply a model template for specifying an H10 model\n");
      fprintf(fp, "  -T, --gen-model=MODEL,FW_MIN_VERSION,FW_MAX_VERSION\n");
      fprintf(fp, "                        Create a model template from an existing database\n");
      fprintf(fp, "  -X, --install-model   Install the specified model template into the player\n");
      fprintf(fp, "\n");
      fprintf(fp, "H10 location options:\n");
      fprintf(fp, "  -s, --systempath=SYSTEM       Specify path to the system directory\n");
      fprintf(fp, "  -d, --dbpath=DATABASE         Specify path to the database\n");
      fprintf(fp, "  -m, --musicpath=MUSIC         Specify root path to the music files\n");
      fprintf(fp, "  -p, --playlistpath=PLAYLIST   Specify path to the playlist files\n");
      fprintf(fp, "\n");
#ifndef           _WIN32
      fprintf(fp, "Language-specific options:\n");
      fprintf(fp, "  -e, --encoding=SE     Specify character encoding used by the operating system\n");
      fprintf(fp, "  -w, --tagencoding=TE  Specify character encoding for parsing non-Unicode tags\n");
#endif/*_WIN32*/
#ifdef      SUPPORT_RTL
      fprintf(fp, "  -l, --rtl             Store Arabic/Hebrew characters in right-to-left order\n");
#endif/*SUPPORT_RTL*/
      fprintf(fp, "\n");
      fprintf(fp, "Miscellaneous options:\n");
      fprintf(fp, "  -D, --dump            Output a database dump in plain text format\n");
      fprintf(fp, "  -V, --version         Show version number and exit\n");
      fprintf(fp, "  -h, --help            Show this help message and exit\n");
      fprintf(fp, "  -v, --verbose         Verbose mode\n");
}

struct tag_progress_data {
      FILE *fp;
      int num;
      int prev_phase;
};
typedef struct tag_progress_data progress_data_t;

static ucs2_char_t ucs2cs_easyh10[] = {'e','a','s','y','h','1','0',0};
static ucs2_char_t ucs2cs_model[] = {'m','o','d','e','l',0};
static ucs2_char_t ucs2cs_easyh10model[] = {'e','a','s','y','h','1','0','.','m','o','d','e','l',0};

#ifndef     _WIN32
static ucs2_char_t ucs2cs_usrlocalshareeasyh10model[] = {'/','u','s','r','/','l','o','c','a','l','/','s','h','a','r','e','/','e','a','s','y','h','1','0','/','m','o','d','e','l',0};
static ucs2_char_t ucs2cs_usrlocalshareeasyh10[] = {'/','u','s','r','/','l','o','c','a','l','/','s','h','a','r','e','/','e','a','s','y','h','1','0',0};
static ucs2_char_t ucs2cs_usrshareeasyh10model[] = {'/','u','s','r','/','s','h','a','r','e','/','e','a','s','y','h','1','0','/','m','o','d','e','l',0};
static ucs2_char_t ucs2cs_usrshareeasyh10[] = {'/','u','s','r','/','s','h','a','r','e','/','e','a','s','y','h','1','0',0};
#endif/*_WIN32*/


static void easyh10_error(void *instance, int code, void *param)
{
      char mbs[MAX_PATH+1];
      progress_data_t* pd = (progress_data_t*)instance;
      FILE *fp = pd->fp;

      switch (code) {
      case EASYH10_ERROR_INITLIBH10DB:
            fprintf(fp, "An error occurred during the initialization of libh10db.\n");
            break;
      case EASYH10_ERROR_LOADTEMPLATE:
            fprintf(fp, "Failed to read the H10 model template (code = %d).\n", *(int*)param);
            break;
      case EASYH10_ERROR_STORETEMPLATE:
            fprintf(fp, "Failed to write the H10 model template (code = %d).\n", *(int*)param);
            break;
      case EASYH10_ERROR_READDB:
            fprintf(fp, "Failed to read the H10 database (code = %d).\n", *(int*)param);
            break;
      case EASYH10_ERROR_WRITEDB:
            fprintf(fp, "Failed to write the H10 database (code = %d).\n", *(int*)param);
            break;
      case EASYH10_ERROR_UPDATEDB:
            fprintf(fp, "Failed to update the database content (code = %d).\n", *(int*)param);
            break;

      case EASYH10_WARNING_PLAYLIST_READ:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param, ucs2len((const ucs2_char_t*)param)+1);
            fprintf(fp, "WARNING: Failed to parse playlist: %s\n", mbs);
            break;
      case EASYH10_WARNING_PLAYLIST_CONVERT:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param, ucs2len((const ucs2_char_t*)param)+1);
            fprintf(fp, "WARNING: Failed to convert playlist: %s\n", mbs);
            break;
      case EASYH10_WARNING_PLAYLIST_CONVERT_ENTRY:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param, ucs2len((const ucs2_char_t*)param)+1);
            fprintf(fp, "WARNING:   %s\n", mbs);
            break;
      case EASYH10_WARNING_PLAYLIST_WRITE:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param, ucs2len((const ucs2_char_t*)param)+1);
            fprintf(fp, "WARNING: Failed to write playlist: %s\n", mbs);
            break;
      }
}

static int database_progress(void *instance, int phase, int param_int, void *param_ptr)
{
      char mbs[MAX_PATH+1];
      progress_data_t* pd = (progress_data_t*)instance;
      FILE *fp = pd->fp;

      switch (phase) {
      /* Enumerating media_targets. */
      case EASYH10P_ENUMTARGETS_START:
            fprintf(fp, "Enumerating music files:\n");
            break;
      case EASYH10P_ENUMTARGETS_FILE:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "  %d: %-70.70s\r", param_int, mbs);
            fflush(fp);
            break;
      case EASYH10P_ENUMTARGETS_END:
            fprintf(fp, "  %d files found.%-60.60s\n", param_int, "");
            fprintf(fp, "\n");
            break;


      /* Reading model template. */
      case EASYH10P_READ_MODEL_START:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "Reading H10 model template:\n");
            /*fprintf(fp, "  %s\n", mbs);*/
            break;
      case EASYH10P_READ_MODEL:
            break;
      case EASYH10P_READ_MODEL_END:
            fprintf(fp, "  %s\n", (const char *)param_ptr);
            fprintf(fp, "\n");
            break;

      case EASYH10P_DB_NUM_EXISTING:
            if (verbose) {
                  fprintf(fp, "INFO: Found %d music files in the database.\n", param_int);
            }
            break;
      case EASYH10P_DB_NUM_NEW:
            if (verbose) {
                  fprintf(fp, "INFO: Found %d music files to be added newly to the database.\n", param_int);
            }
            break;
      case EASYH10P_DB_NUM_DISAPPEARED:
            if (verbose) {
                  fprintf(fp, "INFO: Found %d music files to be removed from the database.\n", param_int);
            }
            break;
      case EASYH10P_DB_NUM_OBTAIN:
            if (verbose) {
                  fprintf(fp, "INFO: Obtain media information from %d music files.\n", param_int);
            }
            break;
      case EASYH10P_DB_NUM_UNUSED:
            if (verbose) {
                  fprintf(fp, "INFO: %d music files are removed from the database.\n", param_int);
            }
            break;

      /* Reading and parsing H10 database. */
      case EASYH10P_READ_START:
            fprintf(fp, "Reading H10 media database\n");
            break;
      case EASYH10P_READ_HDR:
            fprintf(fp, "  %d%%: H10DB.hdr       \r", param_int);
            break;
      case EASYH10P_READ_DAT:
            fprintf(fp, "  %d%%: H10DB.dat       \r", param_int);
            break;
      case EASYH10P_READ_IDX:
            fprintf(fp, "  %d%%: H10DB_*.idx     \r", param_int);
            break;
      case EASYH10P_READ_UPD:
            fprintf(fp, "  %d%%: H10DB.upd       \r", param_int);
            break;
      case EASYH10P_READ_END:
            fprintf(fp, "\n");
            fprintf(fp, "\n");
            break;

      /* Get song information. */
      case EASYH10P_GETINFO_START:
            fprintf(fp, "Obtaining media information from %d files:\n", param_int);
            pd->num = param_int;
            break;
      case EASYH10P_GETINFO_FILE:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "  %d: %-70.70s\r", param_int, mbs);
            break;
      case EASYH10P_GETINFO_END:
            fprintf(fp, "  %d files obtained.%-58.58s\n", param_int, "");
            fprintf(fp, "\n");
            break;

      /* Update. */
      case EASYH10P_UPDATE_START:
            fprintf(fp, "Updating database\r");
            break;
      case EASYH10P_UPDATE_IDX:
            break;
      case EASYH10P_UPDATE_END:
            fprintf(fp, "\n");
            fprintf(fp, "\n");
            break;

      /* Write the databse. */
      case EASYH10P_WRITE_START:
            fprintf(fp, "Writing H10 media database:\n");
            break;
      case EASYH10P_WRITE_IDX:
            fprintf(fp, "  %d%%: (H10DB_*.idx)    \r", param_int);
            break;
      case EASYH10P_WRITE_DAT:
            fprintf(fp, "  %d%%: (H10DB.dat)      \r", param_int);
            break;
      case EASYH10P_WRITE_HDR:
            fprintf(fp, "  %d%%: (H10DB.hdr)      \r", param_int);
            break;
      case EASYH10P_WRITE_UPD:
            fprintf(fp, "  %d%%: (H10DB.upd)      \r", param_int);
            break;
      case EASYH10P_WRITE_END:
            fprintf(fp, "\n");
            fprintf(fp, "\n");
            break;

            /*
      case EASYH10P_UPDATE_CLEAN:
            fprintf(fp, "Updating database: cleaning unused entries %-20s\r", "");
            break;
      case EASYH10P_UPDATE_END:
            fprintf(fp, "Updating database: done. %-40s\n", "");
            break;*/
      }

      pd->prev_phase = phase;
      fflush(fp);
      return 0;

}

static int playlist_progress(void *instance, int phase, int param_int, void *param_ptr)
{
      char mbs[MAX_PATH+1];
      progress_data_t* pd = (progress_data_t*)instance;
      FILE *fp = pd->fp;

      switch (phase) {
      /* Enumerating playlist targets. */
      case EASYH10P_ENUMTARGETS_START:
            fprintf(fp, "Enumerating playlists:\n");
            break;
      case EASYH10P_ENUMTARGETS_FILE:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "  %d: %-70.70s\r", param_int, mbs);
            break;
      case EASYH10P_ENUMTARGETS_END:
            fprintf(fp, "  %d playlists found.%-58.58s\n", param_int, "");
            fprintf(fp, "\n");
            break;

      case EASYH10P_PLAYLIST_ENUMMUSIC_START:
            fprintf(fp, "Enumerating music files:\n");
            break;
      case EASYH10P_PLAYLIST_ENUMMUSIC_FILE:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "  %d: %-70.70s\r", param_int, mbs);
            break;
      case EASYH10P_PLAYLIST_ENUMMUSIC_END:
            fprintf(fp, "  %d files found.%-60.60s\n", param_int, "");
            fprintf(fp, "\n");
            break;

      /* Converting the playlist. */
      case EASYH10P_PLAYLIST_START:
            fprintf(fp, "Converting %d playlists:\n", param_int);
            pd->num = param_int;
            break;
      case EASYH10P_PLAYLIST:
            ucs2tombs(mbs, MAX_PATH, (const ucs2_char_t*)param_ptr, ucs2len((const ucs2_char_t*)param_ptr)+1);
            fprintf(fp, "  %d: %-70.70s\r", param_int, mbs);
            break;
      case EASYH10P_PLAYLIST_END:
            fprintf(fp, "  %d playlists successfully converted.%-40.40s\n", param_int, "");
            fprintf(fp, "\n");
            break;
      }

      pd->prev_phase = phase;
      fflush(fp);
      return 0;
}

int locate_template(ucs2_char_t* pathname, const char *_filename, const ucs2_char_t* path_to_root)
{
      if (_filename) {
            ucs2_char_t* filename = mbsdupucs2(_filename);

            /* Rule-1: current folder. */
            if (filepathutil_file_exists(filename)) {
                  ucs2cpy(pathname, filename);
                  goto exit_locate_template_success;
            }

#ifndef     _WIN32
            /* Rule-2: /usr/local/share/easyh10/model/* */
            ucs2cpy(pathname, ucs2cs_usrlocalshareeasyh10model);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, filename);
            if (filepathutil_file_exists(pathname)) {
                  goto exit_locate_template_success;
            }

            /* Rule-3: /usr/local/share/easyh10/* */
            ucs2cpy(pathname, ucs2cs_usrlocalshareeasyh10);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, filename);
            if (filepathutil_file_exists(pathname)) {
                  goto exit_locate_template_success;
            }

            /* Rule-4: /usr/share/easyh10/model/* */
            ucs2cpy(pathname, ucs2cs_usrshareeasyh10model);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, filename);
            if (filepathutil_file_exists(pathname)) {
                  goto exit_locate_template_success;
            }

            /* Rule-5: /usr/share/easyh10/* */
            ucs2cpy(pathname, ucs2cs_usrshareeasyh10);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, filename);
            if (filepathutil_file_exists(pathname)) {
                  goto exit_locate_template_success;
            }
#endif/*_WIN32*/

            /* Failed to find model template. */
            ucs2cpy(pathname, filename);
            ucs2free(filename);
            return 1;

exit_locate_template_success:
            ucs2free(filename);
            return 0;

      } else {
            /* Rule-1: (path_to_root)/easyh10/easyh10.model */
            ucs2cpy(pathname, path_to_root);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, ucs2cs_easyh10);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, ucs2cs_easyh10model);
            if (filepathutil_file_exists(pathname)) {
                  return 0;
            }

            /* Rule-2: (path_to_root)/easyh10.model */
            ucs2cpy(pathname, path_to_root);
            filepathutil_addslash(pathname);
            ucs2cat(pathname, ucs2cs_easyh10model);
            if (filepathutil_file_exists(pathname)) {
                  return 0;
            }

            /* Failed. */
            return 1;
      }
}

int install_template(const ucs2_char_t* src, const ucs2_char_t* path_to_root)
{
      ucs2_char_t dst[MAX_PATH];

      ucs2cpy(dst, path_to_root);
      filepathutil_addslash(dst);
      ucs2cat(dst, ucs2cs_easyh10model);
      return filepathutil_copyfile(src, dst);
}

#ifndef           _WIN32

int set_encoding(const char *encoding)
{
      ucs2conv_t conv;

      if (ucs2set_encoding(encoding, &conv) != 0) {
            fprintf(stderr, "ERROR: iconv does not support the following conversion\n  %s: from %s to %s\n", encoding, conv.from, conv.to);
            return 1;
      }
}

int set_encoding_music(const char *encoding)
{
      ucs2conv_t conv;

      if (ucs2set_encoding_music(encoding, &conv) != 0) {
            fprintf(stderr, "ERROR: iconv does not support the following conversion\n  %s: from %s to %s\n", encoding, conv.from, conv.to);
            return 1;
      }
}

#endif

#if 0

static int callback(void *instance, const ucs2_char_t* found_path, const ucs2_char_t* found_file)
{
      char *path = ucs2dupmbs(found_path);
      char *file = ucs2dupmbs(found_file);

      fprintf(stdout, "%s%s\n", path, file);

      ucs2free(file);
      ucs2free(path);
      return 0;
}

int main(int argc, char *argv[])
{
      int ret;
      ucs2_char_t *str1 = NULL, *str2 = NULL;
      char *mbs1 = NULL, *mbs2 = NULL;
      setlocale(LC_ALL, "");

      if (ucs2set_encoding("ISO-8859-1") != 0) {
        fprintf("iconv failed\n");
        return 1;
      }

      str1 = mbsdupucs2("Coldplay - A Whisper.mp3");
      str2 = mbsdupucs2("Coldplay - A Rush of Blood to the Head.mp3");
      mbs1 = ucs2dupmbs(str1);
      mbs2 = ucs2dupmbs(str2);

      fprintf(stdout, "%s\n", mbs1);
      fprintf(stdout, "%s\n", mbs2);

      ret = ucs2icmp(str1, str2);
      fprintf(stdout, "%d\n", ret);
      return 0;
}

#else

static const char *mis_p = "{ARTIST}\\";
static const char *mis_pa = "{ARTIST}\\{ALBUM+}\\";
static const char *mis_pat = "{ARTIST}\\{ALBUM+}\\{TITLE}";
static const char *mis_pant = "{ARTIST}\\{ALBUM+}\\{NUMBER}{TITLE}";
static const char *mis_gp = "{GENRE}\\{ARTIST}\\";
static const char *mis_gpa = "{GENRE}\\{ARTIST}\\{ALBUM+}\\";
static const char *mis_gpat = "{GENRE}\\{ARTIST}\\{ALBUM+}\\{TITLE}";
static const char *mis_gpant = "{GENRE}\\{ARTIST}\\{ALBUM+}\\{NUMBER}{TITLE}";


int main(int argc, char *argv[])
{
      int ret = 0;
      int mode = MODE_NONE;
      int easyh10_flag = EASYH10_PLAYLIST_INCREMENTAL;
      const char *template_arg = NULL;
      easyh10_modelenv_t env;
      char *templ = NULL;
      ucs2_char_t path_to_root[MAX_PATH+1];
      ucs2_char_t path_to_system[MAX_PATH+1], path_to_db[MAX_PATH+1];
      ucs2_char_t path_to_music[MAX_PATH+1], path_to_playlist[MAX_PATH+1];
      ucs2_char_t template_filename[MAX_PATH+1];
      ucs2_char_t playlist_extension[MAX_PATH+1];
      const char *media_info_source = NULL;
      FILE *fpi = stdin, *fpo = stdout, *fpe = stderr;
      progress_data_t pd;

      pd.fp = fpe;
      pd.num = 0;
      pd.prev_phase = -1;

      setlocale(LC_ALL, "");

      memset(path_to_root, 0, sizeof(path_to_root));
      memset(path_to_system, 0, sizeof(path_to_system));
      memset(path_to_db, 0, sizeof(path_to_db));
      memset(path_to_music, 0, sizeof(path_to_music));
      memset(path_to_playlist, 0, sizeof(path_to_playlist));
      memset(template_filename, 0, sizeof(template_filename));
      memset(playlist_extension, 0, sizeof(playlist_extension));

      /* Show copyright information. */
      fprintf(fpe, APPLICATION_S " " VERSION_S "  " COPYRIGHT_S "\n");
      fprintf(fpe, "\n");

      /* Set character encoding. */
#ifndef           _WIN32
      ucs2init(MBS_CHARSET);
      if (set_encoding(MBS_CHARSET) != 0) {
            return 1;
      }
      if (set_encoding_music(MBS_CHARSET) != 0) {
            return 1;
      }
#endif/*_WIN32*/

      /* Parse the command-line arguments. */
      for (;;) {
            int this_option_optind = optind ? optind : 1;
            int option_index = 0;
            static const struct option long_options[] = {
                  {"construct",           no_argument,            0, 'C'},
                  {"new",                       no_argument,            0, 'n'},
                  {"incremental",         no_argument,            0, 'i'},
                  {"clean",               no_argument,            0, 'c'},
                  {"update",              no_argument,            0, 'U'},
                  {"order",               required_argument,      0, 'o'},
                  {"source",              required_argument,      0, 'z'},
                  {"playlist",            no_argument,            0, 'P'},
                  {"music",               no_argument,            0, 'M'},
                  {"reconvert",           no_argument,            0, 'r'},
                  {"guess-missing", no_argument,            0, 'g'},
                  {"find-missing",  no_argument,            0, 'f'},
                  {"skip-missing",  no_argument,            0, 'k'},
                  {"model",               required_argument,      0, 't'},
                  {"gen-model",           required_argument,      0, 'T'},
                  {"install-model", no_argument,            0, 'X'},
                  {"systempath",          required_argument,      0, 's'},
                  {"dbpath",              required_argument,      0, 'd'},
                  {"musicpath",           required_argument,      0, 'm'},
                  {"playlistpath",  required_argument,      0, 'p'},
            #ifndef     _WIN32
                  {"encoding",            required_argument,      0, 'e'},
                  {"tagencoding",         required_argument,      0, 'w'},
            #endif/*_WIN32*/
            #ifdef      SUPPORT_RTL
                  {"rtl",                       no_argument,            0, 'l'},
            #endif
                  {"dump",                no_argument,            0, 'D'},
                  {"version",             no_argument,            0, 'V'},
                  {"help",                no_argument,            0, 'h'},
                  {"verbose",             no_argument,            0, 'v'},
                  {NULL, 0, 0, 0}
            };
#ifndef     _WIN32
            int c = getopt_long(argc, argv, "CnicUo:z:PMrgfkt:T:Xs:d:m:p:e:w:lDVhv", long_options, &option_index);
#else
            int c = getopt_long(argc, argv, "CnicUo:z:PMrgfkt:T:Xs:d:m:p:lDVhv", long_options, &option_index);
#endif/*_WIN32*/
            if (c == -1) {
                  break;
            }

            switch (c) {
            case 'C':
                  mode |= MODE_DATABASE;
                  break;
            case 'n':
                  easyh10_flag |= EASYH10_DATABASE_NEW;
                  break;
            case 'i':
                  easyh10_flag |= EASYH10_DATABASE_INCREMENTAL;
                  break;
            case 'c':
                  easyh10_flag |= EASYH10_DATABASE_CLEAN;
                  break;
            case 'U':
                  mode |= MODE_DATABASE;
                  easyh10_flag |= (EASYH10_DATABASE_INCREMENTAL | EASYH10_DATABASE_CLEAN);
                  break;
            case 'o':
                  if (strcmp(optarg, "d") == 0 || strcmp(optarg, "default") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_LEAVE;
                  } else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tracktitle") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_TRACKNAME;
                  } else if (strcmp(optarg, "f") == 0 || strcmp(optarg, "filename") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_FILENAME;
                  } else if (strcmp(optarg, "n") == 0 || strcmp(optarg, "tracknumber") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_TRACKNUMBER;
                  } else if (strcmp(optarg, "c") == 0 || strcmp(optarg, "complete") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_COMPLETERANDOM;
                  } else if (strcmp(optarg, "a") == 0 || strcmp(optarg, "album") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_ALBUMRANDOM;
                  } else if (strcmp(optarg, "l") == 0 || strcmp(optarg, "all") == 0) {
                        easyh10_flag &= EASYH10_DATABASE_ORDERMASK;
                        easyh10_flag |= EASYH10_DATABASE_ORDER_ALLRANDOM;
                  } else {
                        fprintf(fpe, "ERROR: Unrecognized type of track ordering!\n");
                        ret = 1;
                        goto exit_main;
                  }
                  break;
            case 'z':
                  if          (strcmp(optarg, "m") == 0)          media_info_source = NULL;
                  else if     (strcmp(optarg, "p") == 0)          media_info_source = mis_p;
                  else if     (strcmp(optarg, "pa") == 0)         media_info_source = mis_pa;
                  else if     (strcmp(optarg, "pat") == 0)  media_info_source = mis_pat;
                  else if     (strcmp(optarg, "pant") == 0) media_info_source = mis_pant;
                  else if     (strcmp(optarg, "gp") == 0)         media_info_source = mis_gp;
                  else if     (strcmp(optarg, "gpa") == 0)  media_info_source = mis_gpa;
                  else if     (strcmp(optarg, "gpat") == 0) media_info_source = mis_gpat;
                  else if     (strcmp(optarg, "gpant") == 0)      media_info_source = mis_gpant;
                  else {
                        fprintf(fpe, "ERROR: Unrecognized method for obtaining media information!\n");
                        ret = 1;
                        goto exit_main;
                  }
                  break;
            case 'P':
                  mode |= MODE_PLAYLIST;
                  easyh10_flag |= EASYH10_PLAYLIST_PLAYLIST;
                  break;
            case 'M':
                  mode |= MODE_PLAYLIST;
                  easyh10_flag |= EASYH10_PLAYLIST_MUSIC;
                  break;
            case 'r':
                  easyh10_flag &= ~EASYH10_PLAYLIST_INCREMENTAL;
                  break;
            case 'g':
                  easyh10_flag |= EASYH10_PLAYLIST_GUESS_MISSING;
                  break;
            case 'f':
                  easyh10_flag |= EASYH10_PLAYLIST_SEARCH_MISSING;
                  break;
            case 'k':
                  easyh10_flag |= EASYH10_PLAYLIST_SKIP_MISSING;
                  break;

            case 't':
                  ucs2free(templ);
                  templ = strdup(optarg);
                  break;
            case 'T':
                  mode |= MODE_TEMPLATE;
                  template_arg = optarg;
                  break;
            case 'X':
                  mode |= MODE_INSTALL;
                  break;

            case 's':
                  mbstoucs2(path_to_system, MAX_PATH, optarg, strlen(optarg)+1);
                  break;
            case 'd':
                  mbstoucs2(path_to_db, MAX_PATH, optarg, strlen(optarg)+1);
                  break;
            case 'm':
                  mbstoucs2(path_to_music, MAX_PATH, optarg, strlen(optarg)+1);
                  break;
            case 'p':
                  mbstoucs2(path_to_playlist, MAX_PATH, optarg, strlen(optarg)+1);
                  break;

#ifndef           _WIN32
            case 'e':
                  if (set_encoding(optarg) != 0) {
                        ret = 1;
                        goto exit_main;
                  }
                  if (set_encoding_music(optarg) != 0) {
                        ret = 1;
                        goto exit_main;
                  }
                  break;
            case 'w':
                  if (set_encoding_music(optarg) != 0) {
                        ret = 1;
                        goto exit_main;
                  }
                  break;
#endif/*_WIN32*/
            case 'l':
#ifdef      SUPPORT_RTL
                  easyh10_flag |= EASYH10_DATABASE_RIGHTTOLEFT;
#endif
                  break;

            case 'D':
                  mode |= MODE_DUMP;
                  break;
            case 'V':
                  mode |= MODE_VERSION;
                  break;
            case 'h':
                  mode |= MODE_HELP;
                  break;
            case 'v':
                  verbose = 1;
                  break;
            case '?':
                  goto exit_main;
                  break;
            }
      }

      /* Exit when version mode specified. */
      if (mode & MODE_VERSION) {
            goto exit_main;
      }

      /* Show help message. */
      if (mode & MODE_HELP) {
            usage(fpo, argv[0]);
            goto exit_main;
      }

      /* Try to obtain the path to root directory (path_to_root) from the command line. */
    if (optind < argc) {
            size_t length = strlen(argv[optind]);
            if (length > 0) {
                  mbstoucs2(path_to_root, MAX_PATH, argv[optind], strlen(argv[optind])+1);
            }
      }
      /* If path_to_root is not set, use current directory. */
      if (!*path_to_root) {
            if (mode & MODE_INSTALL) {
                  fprintf(fpe, "ERROR: Path to the H10 root directory must be specified.\n");
                  ret = 1;
                  goto exit_main;
            } else {
                  char pwd[MAX_PATH+1];
                  getcwd(pwd, MAX_PATH);
                  mbstoucs2(path_to_root, MAX_PATH, pwd, strlen(pwd)+1);
            }
      }
      filepathutil_addslash(path_to_root);

      /* a model template. */
      if (mode & (MODE_TEMPLATE | MODE_INSTALL)) {
            if (!templ || !*templ) {
                  fprintf(fpe, "ERROR: H10 model template must be specified.\n");
                  ret = 1;
                  goto exit_main;
            }
      }

      /* Obtain pathname to a model template. */
      ret = locate_template(template_filename, templ, path_to_root);
      if (ret == 0 || (mode & MODE_TEMPLATE)) {
            char *mbs = NULL;
            mbs = ucs2dupmbs(template_filename);
            fprintf(fpe, "H10 model template: %s\n", mbs);
            ucs2free(mbs);
      } else {
            fprintf(fpe, "ERROR: H10 model template is not found.\n");
            ret = 1;
            goto exit_main;
      }

      /* Retrieve model-dependent environments. */
      ret = easyh10_get_modelenv(&env, template_filename, NULL, NULL, NULL);
      if (ret == 0) {
            /* Set path to the system directory. */
            if (!*path_to_system) {
                  ucs2cpy(path_to_system, path_to_root);
                  filepathutil_addslash(path_to_system);
                  ucs2cat(path_to_system, env.system_location);
            }

            /* Set path to the database. */
            if (!*path_to_db) {
                  ucs2cpy(path_to_db, path_to_root);
                  filepathutil_addslash(path_to_db);
                  ucs2cat(path_to_db, env.database_location);
            }

            /* Set path to the music. */
            if (!*path_to_music) {
                  ucs2cpy(path_to_music, path_to_root);
                  filepathutil_addslash(path_to_db);
                  ucs2cat(path_to_music, env.music_location);
            }

            /* Set path to the playlist. */
            if (!*path_to_playlist) {
                  ucs2cpy(path_to_playlist, path_to_root);
                  filepathutil_addslash(path_to_db);
                  ucs2cat(path_to_playlist, env.playlist_location);
            }

            /* Set extension for playlists. */
            if (!*playlist_extension) {
                  ucs2cpy(playlist_extension, env.playlist_extension);
            }
      }

      /* Make sure path_to_db. */
      if (mode & (MODE_TEMPLATE | MODE_DATABASE | MODE_DUMP)) {
            if (*path_to_db) {
                  char *mbs = NULL;
                  filepathutil_addslash(path_to_db);
                  mbs = ucs2dupmbs(path_to_db);
                  fprintf(fpe, "Path to database: %s\n", mbs);
                  ucs2free(mbs);
            } else {
                  fprintf(fpe, "ERROR: Path to database is not specified.\n");
                  ret = 1;
                  goto exit_main;
            }
      }

      /* make sure path_to_music. */
      if ((mode & MODE_DATABASE) || (easyh10_flag & EASYH10_PLAYLIST_MUSIC) || (easyh10_flag & EASYH10_PLAYLIST_SEARCH_MISSING)) {
            if (*path_to_music) {
                  char *mbs = NULL;
                  filepathutil_addslash(path_to_music);
                  mbs = ucs2dupmbs(path_to_music);
                  fprintf(fpe, "Path to music: %s\n", mbs);
                  ucs2free(mbs);
            } else {
                  fprintf(fpe, "ERROR: Path to music is not specified.\n");
                  ret = 1;
                  goto exit_main;
            }
      }

      /* make sure path_to_playlist. */
      if (mode & MODE_PLAYLIST) {
            if (*path_to_playlist) {
                  char *mbs = NULL;
                  filepathutil_addslash(path_to_playlist);
                  mbs = ucs2dupmbs(path_to_playlist);
                  fprintf(fpe, "Path to playlist: %s\n", mbs);
                  ucs2free(mbs);
            } else {
                  fprintf(fpe, "ERROR: Path to playlist is not specified.\n");
                  ret = 1;
                  goto exit_main;
            }

            if (playlist_extension) {
                  char *mbs = ucs2dupmbs(playlist_extension);
                  fprintf(fpe, "Playlist extension: %s\n", mbs);
                  ucs2free(mbs);
            } else {
                  fprintf(fpe, "ERROR: Playlist extension is not specified.\n");
                  ret = 1;
                  goto exit_main;
            }
      }

      fprintf(fpe, "\n");

      /* Create template. */
      if (mode & MODE_TEMPLATE) {
            char *p = NULL, *q = NULL;
            int flag = easyh10_flag;
            double fw_min = 0.00, fw_max = 32767.32767;

            easyh10_flag = strtoul(template_arg, &p, 16);
            template_arg = p;

            if (*template_arg == ',') {
                  template_arg++;
                  p = strchr(template_arg, ',');
                  if (p) {
                        p++;
                        fw_min = atof(p);
                        q = strchr(p, '-');
                        if (q) {
                              q++;
                              fw_max = atof(q);
                        } else {
                              fw_max = fw_min;
                        }
                  }
            }

            pd.prev_phase = -1;
            ret = easyh10_generate_template(
                  path_to_db,
                  template_filename,
                  easyh10_flag,
                  (uint16_t)fw_min,
                  (uint16_t)((fw_min - (uint16_t)fw_min) * 100.),
                  (uint16_t)fw_max,
                  (uint16_t)((fw_max - (uint16_t)fw_max) * 100.),
                  &pd,
                  database_progress,
                  easyh10_error
                  );
            if (ret != 0) {
                  fprintf(fpe, "ERROR: Model template generation.\n");
                  goto exit_main;
            }
      }

      /* Install the model file as easyh10.model */
      if (mode & MODE_INSTALL) {
            char *tmp = ucs2dupmbs(path_to_root);
            fprintf(fpe, "Installing: %seasyh10.model\n", tmp, PATHCHAR);
            ucs2free(tmp);

            ret = install_template(template_filename, path_to_root);
            if (ret != 0) {
                  fprintf(fpe, "ERROR: Failed to install a model template.\n");
                  goto exit_main;
            }
            fprintf(fpe, "\n");
      }

      /* Update database. */
      if (mode & MODE_DATABASE) {
            /* We cannot use default playback order with reversed-character mode for a technical reason. */
            if (easyh10_flag & EASYH10_DATABASE_RIGHTTOLEFT) {
                  if ((easyh10_flag & EASYH10_DATABASE_ORDERMASK) == 0) {
                        fprintf(fpe, "ERROR: We cannot use default playback order with right-to-left language mode.\n");
                        goto exit_main;
                  }
            }

            pd.prev_phase = -1;
            ret = easyh10_database(
                  path_to_root,
                  path_to_db,
                  path_to_music,
                  template_filename,
                  media_info_source,
                  easyh10_flag,
                  &pd,
                  database_progress,
                  easyh10_error
                  );
            if (ret != 0) {
                  fprintf(fpe, "ERROR: Database update.\n");
                  goto exit_main;
            }
      }

      /* Convert playlists. */
      if (mode & MODE_PLAYLIST) {
            pd.prev_phase = -1;
            ret = easyh10_playlist(
                  path_to_root,
                  path_to_music,
                  path_to_playlist,
                  playlist_extension,
                  easyh10_flag,
                  &pd,
                  playlist_progress,
                  easyh10_error
                  );

            if (ret != 0) {
                  fprintf(fpe, "ERROR: Playlist conversion.\n");
                  goto exit_main;
            }
      }

      /* Dump the database. */
      if (mode & MODE_DUMP) {
            ret = easyh10_dump(
                  path_to_db,
                  fpo,
                  template_filename,
                  easyh10_flag
                  );
            if (ret != 0) {
                  fprintf(fpe, "ERROR: Database dump.\n");
                  goto exit_main;
            }
      }

exit_main:
      free(templ);
      return ret;
}
#endif

Generated by  Doxygen 1.6.0   Back to index