static int
process_tracks(plist_t tracks)
{
  plist_t trk;
  plist_dict_iter iter;
  char *str;
  uint64_t trk_id;
  uint8_t disabled;
  int ntracks;
  int nloaded;
  int mfi_id;
  int ret;

  if (plist_dict_get_size(tracks) == 0)
    {
      DPRINTF(E_WARN, L_SCAN, "No tracks in iTunes library\n");
      return 0;
    }

  db_transaction_begin();

  ntracks = 0;
  nloaded = 0;

  iter = NULL;
  plist_dict_new_iter(tracks, &iter);

  plist_dict_next_item(tracks, iter, NULL, &trk);
  while (trk)
    {
      if (plist_get_node_type(trk) != PLIST_DICT)
	{
	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      ret = get_dictval_int_from_key(trk, "Track ID", &trk_id);
      if (ret < 0)
	{
	  DPRINTF(E_WARN, L_SCAN, "Track ID not found!\n");

	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      ret = get_dictval_bool_from_key(trk, "Disabled", &disabled);
      if (ret < 0)
	{
	  DPRINTF(E_WARN, L_SCAN, "Malformed track record (id %" PRIu64 ")\n", trk_id);

	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      if (disabled)
	{
	  DPRINTF(E_INFO, L_SCAN, "Track %" PRIu64 " disabled; skipping\n", trk_id);

	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      ret = get_dictval_string_from_key(trk, "Track Type", &str);
      if (ret < 0)
	{
	  DPRINTF(E_WARN, L_SCAN, "Track %" PRIu64 " has no track type\n", trk_id);

	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      if (strcmp(str, "URL") == 0)
	mfi_id = process_track_stream(trk);
      else if (strcmp(str, "File") == 0)
	mfi_id = process_track_file(trk);
      else
	{
	  DPRINTF(E_LOG, L_SCAN, "Unknown track type: '%s'\n", str);

	  free(str);
	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      free(str);

      ntracks++;
      if (ntracks % 200 == 0)
	{
	  DPRINTF(E_LOG, L_SCAN, "Processed %d tracks...\n", ntracks);
	  db_transaction_end();
	  db_transaction_begin();
	}

      if (mfi_id <= 0)
	{
	  plist_dict_next_item(tracks, iter, NULL, &trk);
	  continue;
	}

      ret = id_map_add(trk_id, mfi_id);
      if (ret < 0)
	DPRINTF(E_LOG, L_SCAN, "Out of memory for itml -> db mapping\n");

      nloaded++;

      plist_dict_next_item(tracks, iter, NULL, &trk);
    }

  free(iter);

  db_transaction_end();

  return nloaded;
}
int main(int argc, char **argv)

{

  /*
   * basic declarations
   */

  path_parts_t progname_parts;

  si32 n_track_files, ifile;
  char **track_file_paths;

  date_time_t *scan_time;

  storm_file_handle_t s_handle;
  track_file_handle_t t_handle;

  /*
   * allocate space for the global structure
   */
  
  Glob = (global_t *)
    umalloc((ui32) sizeof(global_t));

  /*
   * set program name
   */
  
  uparse_path(argv[0], &progname_parts);
  Glob->prog_name = (char *)
    umalloc ((ui32) (strlen(progname_parts.base) + 1));
  strcpy(Glob->prog_name, progname_parts.base);
  
  /*
   * load up parameters data base
   */
  
  Glob->params_path_name = uparams_read(argv, argc, Glob->prog_name);

  /*
   * parse command line arguments
   */

  parse_args(argc, argv, &n_track_files, &track_file_paths);

  /*
   * initialize
   */

  init_indices(&s_handle, &t_handle);

  /*
   * print comments to start of file
   */

  print_comments(stdout);

  /*
   * loop through the track files
   */
  
  for (ifile = 0; ifile < n_track_files; ifile++) {

    fprintf(stderr, "\nProcessing file %s\n",
	    track_file_paths[ifile]);

    /*
     * open track and storm files
     */
    
    open_files(&s_handle, &t_handle, track_file_paths, ifile);
  
    /*
     * load scan time array
     */

    scan_time = load_scan_times(&s_handle);

    /*
     * read in track utime array
     */

    if (RfReadTrackUtime(&t_handle, "main") != R_SUCCESS)
      tidy_and_exit(-1);

    /*
     * process the track file, producing forecast grids
     */

    process_track_file(&s_handle, &t_handle, scan_time);

    /*
     * close files
     */

    RfCloseStormFiles(&s_handle, "main");
    RfCloseTrackFiles(&t_handle, "main");

  }

  /*
   * quit
   */
  
  tidy_and_exit(0);

  return(0);

}