示例#1
0
int ft_build_playlist(struct tree_context* c, int start_index)
{
    int i;
    int start=start_index;

    tree_lock_cache(c);
    struct entry *entries = tree_get_entries(c);

    for(i = 0;i < c->filesindir;i++)
    {
        if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO)
        {
            if (playlist_add(entries[i].name) < 0)
                break;
        }
        else
        {
            /* Adjust the start index when se skip non-MP3 entries */
            if(i < start)
                start_index--;
        }
    }

    tree_unlock_cache(c);

    return start_index;
}
示例#2
0
文件: playlist.c 项目: 0x0all/mpv
void playlist_append_entries(struct playlist *pl, struct playlist *source_pl)
{
    while (source_pl->first) {
        struct playlist_entry *e = source_pl->first;
        playlist_unlink(source_pl, e);
        playlist_add(pl, e);
    }
}
示例#3
0
文件: castget.c 项目: mlj/castget
static void update_callback(void *user_data, channel_action action,
                            channel_info *channel_info, enclosure *enclosure,
                            const gchar *filename)
{
  struct channel_configuration *c = (struct channel_configuration *)user_data;

  switch (action) {
  case CCA_RSS_DOWNLOAD_START:
    if (!quiet)
      g_printf("Updating channel %s...\n", c->identifier);
    break;

  case CCA_RSS_DOWNLOAD_END:
    break;

  case CCA_ENCLOSURE_DOWNLOAD_START:
    g_assert(channel_info);
    g_assert(enclosure);

    if (verbose)
      _print_item_update(enclosure, filename);

    break;

  case CCA_ENCLOSURE_DOWNLOAD_END:
    g_assert(channel_info);
    g_assert(enclosure);
    g_assert(filename);

    /* Set media tags. */
    if (enclosure->type && !strcmp(enclosure->type, "audio/mpeg")) {
#ifdef ENABLE_ID3LIB
      if (_id3_check_and_set(filename, c))
        fprintf(stderr, "Error setting ID3 tag for file %s.\n", filename);
#endif /* ENABLE_ID3LIB */
    }

    /* Update playlist. */
    if (c->playlist) {
      playlist_add(c->playlist, filename);

      if (verbose)
        printf(" * Added downloaded enclosure %s to playlist %s.\n",
               filename, c->playlist);
    }
    break;
  }
}
示例#4
0
static int parse_m3u(struct pl_parser *p)
{
    bstr line = bstr_strip(pl_get_line(p));
    if (p->probing && !bstr_equals0(line, "#EXTM3U")) {
        // Last resort: if the file extension is m3u, it might be headerless.
        if (p->check_level == DEMUX_CHECK_UNSAFE) {
            char *ext = mp_splitext(p->real_stream->url, NULL);
            bstr data = stream_peek(p->real_stream, PROBE_SIZE);
            if (ext && data.len > 10 && maybe_text(data)) {
                const char *exts[] = {"m3u", "m3u8", NULL};
                for (int n = 0; exts[n]; n++) {
                    if (strcasecmp(ext, exts[n]) == 0)
                        goto ok;
                }
            }
        }
        return -1;
    }

ok:
    if (p->probing)
        return 0;

    char *title = NULL;
    while (line.len || !pl_eof(p)) {
        if (bstr_eatstart0(&line, "#EXTINF:")) {
            bstr duration, btitle;
            if (bstr_split_tok(line, ",", &duration, &btitle) && btitle.len) {
                talloc_free(title);
                title = bstrto0(NULL, btitle);
            }
        } else if (bstr_startswith0(line, "#EXT-X-")) {
            p->format = "hls";
        } else if (line.len > 0 && !bstr_startswith0(line, "#")) {
            char *fn = bstrto0(NULL, line);
            struct playlist_entry *e = playlist_entry_new(fn);
            talloc_free(fn);
            e->title = talloc_steal(e, title);
            title = NULL;
            playlist_add(p->pl, e);
        }
        line = bstr_strip(pl_get_line(p));
    }
    talloc_free(title);
    return 0;
}
示例#5
0
文件: playlist.c 项目: 0x0all/mpv
void playlist_shuffle(struct playlist *pl)
{
    struct playlist_entry *save_current = pl->current;
    bool save_replaced = pl->current_was_replaced;
    int count = playlist_count(pl);
    struct playlist_entry **arr = talloc_array(NULL, struct playlist_entry *,
                                               count);
    for (int n = 0; n < count; n++) {
        arr[n] = pl->first;
        playlist_unlink(pl, pl->first);
    }
    for (int n = 0; n < count; n++) {
        int other = (int)((double)(count) * rand() / (RAND_MAX + 1.0));
        struct playlist_entry *tmp = arr[n];
        arr[n] = arr[other];
        arr[other] = tmp;
    }
    for (int n = 0; n < count; n++)
        playlist_add(pl, arr[n]);
    talloc_free(arr);
    pl->current = save_current;
    pl->current_was_replaced = save_replaced;
}
示例#6
0
int ft_build_playlist(struct tree_context* c, int start_index)
{
    int i;
    int start=start_index;

    struct entry *dircache = c->dircache;

    for(i = 0;i < c->filesindir;i++)
    {
        if((dircache[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO)
        {
            if (playlist_add(dircache[i].name) < 0)
                break;
        }
        else
        {
            /* Adjust the start index when se skip non-MP3 entries */
            if(i < start)
                start_index--;
        }
    }

    return start_index;
}
示例#7
0
文件: castget.c 项目: siam28/castget
static void update_callback(void *user_data, channel_action action,
                            channel_info *channel_info, enclosure *enclosure,
                            const gchar *filename)
{
  struct channel_configuration *c = (struct channel_configuration *)user_data;

  switch (action) {
  case CCA_RSS_DOWNLOAD_START:
    if (!quiet)
      g_printf("Updating channel %s...\n", c->identifier);
    break;

  case CCA_RSS_DOWNLOAD_END:
    break;

  case CCA_ENCLOSURE_DOWNLOAD_START:
    g_assert(channel_info);
    g_assert(enclosure);

    if (verbose) {
      if (enclosure->length > 1024*1024*1024) {
        g_printf(" * Downloading %s (%.1f GB) from %s\n",
                 enclosure->filename, (float)enclosure->length / (1024.0*1024.0*1024.0),
                 channel_info->title);
      } else if (enclosure->length > 1024*1024) {
        g_printf(" * Downloading %s (%.1f MB) from %s\n",
                 enclosure->filename, (float)enclosure->length / (1024.0*1024.0),
                 channel_info->title);
      } else if (enclosure->length > 1024) {
        g_printf(" * Downloading %s (%.1f kB) from %s\n",
                 enclosure->filename, (float)enclosure->length / 1024.0,
                 channel_info->title);
      } else if (enclosure->length > 0) {
        g_printf(" * Downloading %s (%ld bytes) from %s\n",
                 enclosure->filename, enclosure->length,
                 channel_info->title);
      } else {
        g_printf(" * Downloading %s from %s\n",
                 enclosure->filename,
                 channel_info->title);
      }
    }
    break;

  case CCA_ENCLOSURE_DOWNLOAD_END:
    g_assert(channel_info);
    g_assert(enclosure);
    g_assert(filename);

    /* Set media tags. */
    if (enclosure->type && !strcmp(enclosure->type, "audio/mpeg")) {
#ifdef ENABLE_ID3LIB
      if (_id3_check_and_set(filename, c))
        fprintf(stderr, "Error setting ID3 tag for file %s.\n", filename);
#endif /* ENABLE_ID3LIB */
    }

    /* Update playlist. */
    if (c->playlist) {
      playlist_add(c->playlist, filename);

      if (verbose)
        printf(" * Added downloaded enclosure %s to playlist %s.\n",
               filename, c->playlist);
    }
    break;
  }
}
示例#8
0
playlist_t *
playlist_read(const char *filename)
{
	playlist_t	*pl;
	unsigned long	 line;
	FILE		*filep;
	char		 buf[PATH_MAX];

	if (filename != NULL) {
		pl = playlist_create(filename);

		if ((filep = fopen(filename, "r")) == NULL) {
			printf("%s: %s: %s\n", __progname, filename, strerror(errno));
			playlist_free(&pl);
			return (NULL);
		}
	} else {
		pl = playlist_create("stdin");

		if ((filep = fdopen(STDIN_FILENO, "r")) == NULL) {
			printf("%s: stdin: %s\n", __progname, strerror(errno));
			playlist_free(&pl);
			return (NULL);
		}
	}

	line = 0;
	while (fgets(buf, (int)sizeof(buf), filep) != NULL) {
		line++;

		if (strlen(buf) == sizeof(buf) - 1) {
			char skip_buf[2];

			printf("%s[%lu]: File or path name too long\n",
			       pl->filename, line);
			/* Discard any excess chars in that line. */
			while (fgets(skip_buf, (int)sizeof(skip_buf), filep) != NULL) {
				if (skip_buf[0] == '\n')
					break;
			}
			continue;
		}

		/*
		 * fgets() would happily fill a buffer with
		 * { '\0', ..., '\n', '\0' }. Also skip lines that begin with
		 * a '#', which is considered a comment.
		 */
		if (buf[0] == '\0' || buf[0] == '#')
			continue;

		/* Trim any trailing newlines and carriage returns. */
		buf[strcspn(buf, "\n")] = '\0';
		buf[strcspn(buf, "\r")] = '\0';

		/* Skip lines that are empty after the trimming. */
		if (buf[0] == '\0')
			continue;

		/* We got one. */
		if (!playlist_add(pl, buf)) {
			fclose(filep);
			playlist_free(&pl);
			return (NULL);
		}
	}
	if (ferror(filep)) {
		printf("%s: playlist_read(): Error while reading %s: %s\n",
		       __progname, pl->filename, strerror(errno));
		fclose(filep);
		playlist_free(&pl);
		return (NULL);
	}

	fclose(filep);
	return (pl);
}
示例#9
0
文件: playlist.c 项目: 0x0all/mpv
void playlist_add_file(struct playlist *pl, const char *filename)
{
    playlist_add(pl, playlist_entry_new(filename));
}
示例#10
0
int main(int argc, char *argv[])
{
  int i;
  char configname[PATH_MAX] = "";
  char playername[PATH_MAX] = "";
  char scorename[PATH_MAX] = "";
  int playernamegiven = 0;
  char tmpstr[PATH_MAX + 256];
  long subsong = -1;
  FILE *listfile = NULL;
  int have_modules = 0;
  int ret;
  char *endptr;
  int uadeconf_loaded, songconf_loaded;
  char songconfname[PATH_MAX] = "";
  char uadeconfname[PATH_MAX];
  struct uade_config uc_cmdline;
  char songoptions[256] = "";
  int have_song_options = 0;
  int plistdir;
  int scanmode = 0;

  struct uade_state state = {};
  char *basedir;

  enum {
    OPT_FIRST = 0x1FFF,
    OPT_BASEDIR,
    OPT_REPEAT,
    OPT_SCAN,
    OPT_SCOPE,
    OPT_SET,
    OPT_STDERR,
    OPT_VERSION
  };

  struct option long_options[] = {
    {"ao-option",        1, NULL, UC_AO_OPTION},
    {"basedir",          1, NULL, OPT_BASEDIR},
    {"buffer-time",      1, NULL, UC_BUFFER_TIME},
    {"cygwin",           0, NULL, UC_CYGWIN_DRIVE_WORKAROUND},
    {"debug",            0, NULL, 'd'},
    {"detect-format-by-content", 0, NULL, UC_CONTENT_DETECTION},
    {"disable-timeouts", 0, NULL, UC_DISABLE_TIMEOUTS},
    {"enable-timeouts",  0, NULL, UC_ENABLE_TIMEOUTS},
    {"ep-option",        1, NULL, 'x'},
    {"filter",           2, NULL, UC_FILTER_TYPE},
    {"force-led",        1, NULL, UC_FORCE_LED},
    {"frequency",        1, NULL, UC_FREQUENCY},
    {"gain",             1, NULL, 'G'},
    {"get-info",         0, NULL, 'g'},
    {"headphones",       0, NULL, UC_HEADPHONES},
    {"headphones2",      0, NULL, UC_HEADPHONES2},
    {"help",             0, NULL, 'h'},
    {"ignore",           0, NULL, 'i'},
    {"interpolator",     1, NULL, UC_RESAMPLER},
    {"jump",             1, NULL, 'j'},
    {"keys",             1, NULL, 'k'},
    {"list",             1, NULL, '@'},
    {"magic",            0, NULL, UC_CONTENT_DETECTION},
    {"no-ep-end-detect", 0, NULL, 'n'},
    {"no-song-end",      0, NULL, 'n'},
    {"normalise",        2, NULL, UC_NORMALISE},
    {"ntsc",             0, NULL, UC_NTSC},
    {"one",              0, NULL, '1'},
    {"pal",              0, NULL, UC_PAL},
    {"panning",          1, NULL, 'p'},
    {"recursive",        0, NULL, 'r'},
    {"repeat",           0, NULL, OPT_REPEAT},
    {"resampler",        1, NULL, UC_RESAMPLER},
    {"scan",             0, NULL, OPT_SCAN},
    {"scope",            0, NULL, OPT_SCOPE},
    {"shuffle",          0, NULL, 'z'},
    {"set",              1, NULL, OPT_SET},
    {"silence-timeout",  1, NULL, 'y'},
    {"speed-hack",       0, NULL, UC_SPEED_HACK},
    {"stderr",           0, NULL, OPT_STDERR},
    {"stdout",           0, NULL, 'c'},
    {"subsong",          1, NULL, 's'},
    {"subsong-timeout",  1, NULL, 'w'},
    {"timeout",          1, NULL, 't'},
    {"verbose",          0, NULL, 'v'},
    {"version",          0, NULL, OPT_VERSION},
    {NULL,               0, NULL, 0}
  };

  uade_config_set_defaults(&uc_cmdline);

  if (!playlist_init(&uade_playlist))
    die("Can not initialize playlist.\n");

#define GET_OPT_STRING(x) if (strlcpy((x), optarg, sizeof(x)) >= sizeof(x)) { die("Too long a string for option %c.\n", ret); }

  while ((ret = getopt_long(argc, argv, "@:1cde:f:gG:hij:k:np:P:rs:S:t:u:vw:x:y:z", long_options, 0)) != -1) {
    switch (ret) {

    case '@':
      listfile = fopen(optarg, "r");
      if (listfile == NULL)
    die("Can not open list file: %s\n", optarg);
      break;

    case '1':
      uade_set_config_option(&uc_cmdline, UC_ONE_SUBSONG, NULL);
      break;

    case 'c':
      strlcpy(uade_output_file_name, "/dev/stdout", sizeof uade_output_file_name);
      /* Output sample data to stdout so do not print anything on stdout */
      uade_terminal_file = stderr;
      break;

    case 'd':
      debug_mode = 1;
      uade_debug_trigger = 1;
      break;
    case 'e':
      GET_OPT_STRING(uade_output_file_format);
      break;

    case 'f':
      GET_OPT_STRING(uade_output_file_name);
      break;

    case 'g':
      uade_info_mode = 1;
      uade_no_audio_output = 1;
      uade_no_text_output = 1;
      uade_set_config_option(&uc_cmdline, UC_ACTION_KEYS, "off");
      break;

    case 'G':
      uade_set_config_option(&uc_cmdline, UC_GAIN, optarg);
      break;

    case 'h':
      print_help();
      exit(0);

    case 'i':
      uade_set_config_option(&uc_cmdline, UC_IGNORE_PLAYER_CHECK, NULL);
      break;

    case 'j':
      uade_jump_pos = strtod(optarg, &endptr);
      if (*endptr != 0 || uade_jump_pos < 0.0)
    die("Invalid jump position: %s\n", optarg);
      break;

    case 'k':
      uade_set_config_option(&uc_cmdline, UC_ACTION_KEYS, optarg);
      break;

    case 'n':
      uade_set_config_option(&uc_cmdline, UC_NO_EP_END, NULL);
      break;

    case 'p':
      uade_set_config_option(&uc_cmdline, UC_PANNING_VALUE, optarg);
      break;

    case 'P':
      GET_OPT_STRING(playername);
      playernamegiven = 1;
      have_modules = 1;
      break;

    case 'r':
      uade_set_config_option(&uc_cmdline, UC_RECURSIVE_MODE, NULL);
      break;

    case 's':
      subsong = strtol(optarg, &endptr, 10);
      if (*endptr != 0 || subsong < 0 || subsong > 255)
    die("Invalid subsong string: %s\n", optarg);
      break;

    case 'S':
      GET_OPT_STRING(scorename);
      break;

    case 't':
      uade_set_config_option(&uc_cmdline, UC_TIMEOUT_VALUE, optarg);
      break;

    case 'u':
      GET_OPT_STRING(uadename);
      break;

    case 'v':
      uade_set_config_option(&uc_cmdline, UC_VERBOSE, NULL);
      break;

    case 'w':
      uade_set_config_option(&uc_cmdline, UC_SUBSONG_TIMEOUT_VALUE, optarg);
      break;

    case 'x':
      uade_set_config_option(&uc_cmdline, UC_EAGLEPLAYER_OPTION, optarg);
      break;

    case 'y':
      uade_set_config_option(&uc_cmdline, UC_SILENCE_TIMEOUT_VALUE, optarg);
      break;

    case 'z':
      uade_set_config_option(&uc_cmdline, UC_RANDOM_PLAY, NULL);
      break;

    case '?':
    case ':':
      exit(1);

    case OPT_BASEDIR:
      uade_set_config_option(&uc_cmdline, UC_BASE_DIR, optarg);
      break;

    case OPT_REPEAT:
      playlist_repeat(&uade_playlist);
      break;

    case OPT_SCAN:
      scanmode = 1;
      /* Set recursive mode in scan mode */
      uade_set_config_option(&uc_cmdline, UC_RECURSIVE_MODE, NULL);
      break;

    case OPT_SCOPE:
      uade_no_text_output = 1;
      uade_set_config_option(&uc_cmdline, UC_USE_TEXT_SCOPE, NULL);
      break;

    case OPT_SET:
      have_song_options = 1;
      strlcpy(songoptions, optarg, sizeof songoptions);
      break;

    case OPT_STDERR:
      uade_terminal_file = stderr;
      break;

    case OPT_VERSION:
      printf("uade123 %s\n", UADE_VERSION);
      exit(0);
      break;

    case UC_AO_OPTION:
    case UC_BUFFER_TIME:
    case UC_FILTER_TYPE:
    case UC_FORCE_LED:
    case UC_FREQUENCY:
    case UC_NORMALISE:
    case UC_RESAMPLER:
      uade_set_config_option(&uc_cmdline, ret, optarg);
      break;

    case UC_CONTENT_DETECTION:
    case UC_CYGWIN_DRIVE_WORKAROUND:
    case UC_DISABLE_TIMEOUTS:
    case UC_ENABLE_TIMEOUTS:
    case UC_HEADPHONES:
    case UC_HEADPHONES2:
    case UC_NTSC:
    case UC_PAL:
    case UC_SPEED_HACK:
      uade_set_config_option(&uc_cmdline, ret, NULL);
      break;

    default:
      die("Impossible option.\n");
    }
  }

  basedir = NULL;
  if (uc_cmdline.basedir_set) {
      basedir = uc_cmdline.basedir.name;
  }
  
  uadeconf_loaded = uade_load_initial_config(&state, uadeconfname, sizeof uadeconfname, basedir);

  /* Merge loaded configurations and command line options */
  uade_merge_configs(&state.config, &uc_cmdline);

  if (uadeconf_loaded == 0) {
    debug(state.config.verbose, "Not able to load uade.conf from ~/.uade2/ or %s/.\n", state.config.basedir.name);
  } else {
    debug(state.config.verbose, "Loaded configuration: %s\n", uadeconfname);
  }

  songconf_loaded = uade_load_initial_song_conf(songconfname, sizeof songconfname, &state.permconfig, &uc_cmdline, &state);

  if (songconf_loaded == 0) {
    debug(state.config.verbose, "Not able to load song.conf from ~/.uade2/ or %s/.\n", state.config.basedir.name);
  } else {
    debug(state.config.verbose, "Loaded song.conf: %s\n", songconfname);
  }

  /* Read play list from file */
  if (listfile != NULL) {
    while (xfgets(tmpstr, sizeof(tmpstr), listfile) != NULL) {
      if (tmpstr[0] == '#')
    continue;
      if (tmpstr[strlen(tmpstr) - 1] == '\n')
    tmpstr[strlen(tmpstr) - 1] = 0;
      playlist_add(&uade_playlist, tmpstr, state.config.recursive_mode, state.config.cygwin_drive_workaround);
    }
    fclose(listfile);
    listfile = NULL;
    have_modules = 1;
  }

  /* Read play list from command line parameters */
  for (i = optind; i < argc; i++) {
    /* Play files */
    playlist_add(&uade_playlist, argv[i], uc_eff.recursive_mode, uc_eff.cygwin_drive_workaround);
    have_modules = 1;
  }

  if (scanmode) {
    scan_playlist(&state.config);
    exit(0);
  }

  if (have_song_options) {
    set_song_options(&songconf_loaded, songoptions, songconfname, sizeof songconfname);
    exit(0);
  }

  load_content_db(&state.config, &state);

  if (state.config.random_play)
    playlist_randomize(&uade_playlist);

  if (have_modules == 0) {
    print_help();
    exit(0);
  }

  /* we want to control terminal differently in debug mode */
  if (debug_mode)
    state.config.action_keys = 0;

  if (state.config.action_keys)
    setup_terminal();

  do {
    DIR *bd = opendir(state.config.basedir.name);
    if (bd == NULL)
      dieerror("Could not access dir %s", state.config.basedir.name);

    closedir(bd);

    snprintf(configname, sizeof configname, "%s/uaerc", state.config.basedir.name);

    if (scorename[0] == 0)
      snprintf(scorename, sizeof scorename, "%s/score", state.config.basedir.name);

    if (uadename[0] == 0)
      strlcpy(uadename, UADE_CONFIG_UADE_CORE, sizeof uadename);

    if (access(configname, R_OK))
      dieerror("Could not read %s", configname);

    if (access(scorename, R_OK))
      dieerror("Could not read %s", scorename);

    if (access(uadename, X_OK))
      dieerror("Could not execute %s", uadename);

  } while (0);

  setup_sighandlers();

  uade_spawn(&state, uadename, configname);

  if (!audio_init(&state.config))
    goto cleanup;

  plistdir = UADE_PLAY_CURRENT;

  while (1) {

    ssize_t filesize;

    /* modulename and songname are a bit different. modulename is the name
       of the song from uadecore's point of view and songname is the
       name of the song from user point of view. Sound core considers all
       custom songs to be players (instead of modules) and therefore modulename
       will become a zero-string with custom songs. */
    char modulename[PATH_MAX];
    char songname[PATH_MAX];

    if (!playlist_get(modulename, sizeof modulename, &uade_playlist, plistdir))
      break;

    plistdir = UADE_PLAY_NEXT;

    state.config = state.permconfig;
    state.song = NULL;
    state.ep = NULL;

    if (uc_cmdline.verbose)
      state.config.verbose = 1;

    if (playernamegiven == 0) {
      debug(state.config.verbose, "\n");

      if (!uade_is_our_file(modulename, 0, &state)) {
    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Unknown format: %s\n", modulename);
    continue;
      }

      debug(state.config.verbose, "Player candidate: %s\n", state.ep->playername);

      if (strcmp(state.ep->playername, "custom") == 0) {
    strlcpy(playername, modulename, sizeof playername);
    modulename[0] = 0;
      } else {
    snprintf(playername, sizeof playername, "%s/players/%s", uc_cmdline.basedir.name, state.ep->playername);
      }
    }

    if (strlen(playername) == 0) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Error: an empty player name given\n");
      goto cleanup;
    }

    /* If no modulename given, try the playername as it can be a custom song */
    strlcpy(songname, modulename[0] ? modulename : playername, sizeof songname);

    if (!uade_alloc_song(&state, songname)) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not read %s: %s\n", songname, strerror(errno));
      continue;
    }

    /* The order of parameter processing is important:
     * 0. set uade.conf options (done before this)
     * 1. set eagleplayer attributes
     * 2. set song attributes
     * 3. set command line options
     */

    if (state.ep != NULL)
      uade_set_ep_attributes(&state);

    if (uade_set_song_attributes(&state, playername, sizeof playername)) {
      debug(state.config.verbose, "Song rejected based on attributes: %s\n",
        state.song->module_filename);
      uade_unalloc_song(&state);
      continue;
    }

    uade_merge_configs(&state.config, &uc_cmdline);

    /* Now we have the final configuration in "uc". */

    uade_set_effects(&state);

    if ((filesize = stat_file_size(playername)) < 0) {
      __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Can not find player: %s (%s)\n", playername, strerror(errno));
      uade_unalloc_song(&state);
      continue;
    }

    debug(state.config.verbose, "Player: %s (%zd bytes)\n", playername, filesize);

    __android_log_print(ANDROID_LOG_VERBOSE, "UADE", "Song: %s (%zd bytes)\n", state.song->module_filename, state.song->bufsize);

    ret = uade_song_initialization(scorename, playername, modulename, &state);
    switch (ret) {
    case UADECORE_INIT_OK:
      break;

    case UADECORE_INIT_ERROR:
      uade_unalloc_song(&state);
      goto cleanup;

    case UADECORE_CANT_PLAY:
    debug(state.config.verbose, "Uadecore refuses to play the song.\n");
    uade_unalloc_song(&state);
    continue; /* jump to the beginning of playlist loop */

    default:
      die("Unknown error from uade_song_initialization()\n");
    }

    if (subsong >= 0)
      uade_set_subsong(subsong, &state.ipc);

    plistdir = play_loop(&state);

    uade_unalloc_song(&state);

    if (plistdir == UADE_PLAY_FAILURE)
      goto cleanup;
    else if (plistdir == UADE_PLAY_EXIT)
      break;
  }

  debug(uc_cmdline.verbose || state.permconfig.verbose, "Killing child (%d).\n", uadepid);
  cleanup(&state);
  return 0;

 cleanup:
  cleanup(&state);
  return 1;
}