/* Load M3U file into plist. Return the number of items read. */ static int plist_load_m3u (struct plist *plist, const char *fname, const char *cwd, const int load_serial) { FILE *file; char *line; int last_added = -1; int after_extinf = 0; int added = 0; if (!(file = fopen(fname, "r"))) { error ("Can't open playlist file: %s", strerror(errno)); return 0; } if (flock(fileno(file), LOCK_SH) == -1) logit ("Can't flock() the playlist file: %s", strerror(errno)); while ((line = read_line(file))) { if (!strncmp(line, "#EXTINF:", sizeof("#EXTINF:")-1)) { char *comma; char *num_err; char time_text[10] = ""; int time_sec; if (after_extinf) { error ("Broken M3U file: double " "#EXTINF."); free (line); plist_delete (plist, last_added); return added; } /* Find the comma */ comma = strchr (line + (sizeof("#EXTINF:") - 1), ','); if (!comma) { error ("Broken M3U file: no comma " "in #EXTINF."); free (line); return added; } /* Get the time string */ time_text[sizeof(time_text)-1] = 0; strncpy (time_text, line + sizeof("#EXTINF:") - 1, MIN(comma - line - (sizeof("#EXTINF:") - 1), sizeof(time_text))); if (time_text[sizeof(time_text)-1]) { error ("Broken M3U file: " "wrong time."); free (line); return added; } /* Extract the time */ time_sec = strtol (time_text, &num_err, 10); if (*num_err) { error ("Broken M3U file: " "time is not a number."); free (line); return added; } after_extinf = 1; last_added = plist_add (plist, NULL); plist_set_title_tags (plist, last_added, comma + 1); if (*time_text) plist_set_item_time (plist, last_added, time_sec); } else if (line[0] != '#') { char path[2*PATH_MAX]; strip_string (line); if (strlen(line) <= PATH_MAX) { make_path (path, sizeof(path), cwd, line); if (plist_find_fname(plist, path) == -1) { if (after_extinf) plist_set_file (plist, last_added, path); else plist_add (plist, path); added++; } else if (after_extinf) plist_delete (plist, last_added); } else if (after_extinf) plist_delete (plist, last_added); after_extinf = 0; } else if (load_serial && !strncmp(line, "#MOCSERIAL: ", sizeof("#MOCSERIAL: ") - 1)) { char *serial_str = line + sizeof("#MOCSERIAL: ") - 1; if (serial_str[0]) { char *err; long serial; serial = strtol (serial_str, &err, 0); if (!*err) { plist_set_serial (plist, serial); logit ("Got MOCSERIAL tag with serial %d", (int)serial); } } } free (line); } if (flock(fileno(file), LOCK_UN) == -1) logit ("Can't flock() (unlock) the playlist file: %s", strerror(errno)); fclose (file); return added; }
/* Load M3U file into plist. Return the number of items read. */ static int plist_load_m3u (struct plist *plist, const char *fname, const char *cwd, const int load_serial) { FILE *file; char *line = NULL; int last_added = -1; int after_extinf = 0; int added = 0; struct flock read_lock = {.l_type = F_RDLCK, .l_whence = SEEK_SET}; file = fopen (fname, "r"); if (!file) { error_errno ("Can't open playlist file", errno); return 0; } /* Lock gets released by fclose(). */ if (fcntl (fileno (file), F_SETLKW, &read_lock) == -1) log_errno ("Can't lock the playlist file", errno); while ((line = read_line (file))) { if (!strncmp (line, "#EXTINF:", sizeof("#EXTINF:") - 1)) { char *comma, *num_err; char time_text[10] = ""; int time_sec; if (after_extinf) { error ("Broken M3U file: double #EXTINF!"); plist_delete (plist, last_added); goto err; } /* Find the comma */ comma = strchr (line + (sizeof("#EXTINF:") - 1), ','); if (!comma) { error ("Broken M3U file: no comma in #EXTINF!"); goto err; } /* Get the time string */ time_text[sizeof(time_text) - 1] = 0; strncpy (time_text, line + sizeof("#EXTINF:") - 1, MIN(comma - line - (sizeof("#EXTINF:") - 1), sizeof(time_text))); if (time_text[sizeof(time_text) - 1]) { error ("Broken M3U file: wrong time!"); goto err; } /* Extract the time. */ time_sec = strtol (time_text, &num_err, 10); if (*num_err) { error ("Broken M3U file: time is not a number!"); goto err; } after_extinf = 1; last_added = plist_add (plist, NULL); plist_set_title_tags (plist, last_added, comma + 1); if (*time_text) plist_set_item_time (plist, last_added, time_sec); } else if (line[0] != '#') { char path[2 * PATH_MAX]; strip_string (line); if (strlen (line) <= PATH_MAX) { make_path (path, sizeof(path), cwd, line); if (plist_find_fname (plist, path) == -1) { if (after_extinf) plist_set_file (plist, last_added, path); else plist_add (plist, path); added += 1; } else if (after_extinf) plist_delete (plist, last_added); } else if (after_extinf) plist_delete (plist, last_added); after_extinf = 0; } else if (load_serial && !strncmp (line, "#MOCSERIAL: ", sizeof("#MOCSERIAL: ") - 1)) { char *serial_str = line + sizeof("#MOCSERIAL: ") - 1; if (serial_str[0]) { char *err; long serial; serial = strtol (serial_str, &err, 0); if (!*err) { plist_set_serial (plist, serial); logit ("Got MOCSERIAL tag with serial %ld", serial); } } } free (line); } err: free (line); fclose (file); return added; }