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

playlist.c

/*
 *      M3U/M3U8/PLS playlist routine.
 *
 *      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: playlist.c,v 1.12 2006/01/23 02:02:04 nyaochi Exp $ */

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

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

#include "filepathutil.h"

#include <playlist.h>

void playlist_init(playlist_t* pl)
{
      pl->num_entries = 0;
      pl->entries = 0;
}

void playlist_finish(playlist_t *pl)
{
      free(pl->entries);
}

static char *strip(char *line)
{
      char *p = line;
      while (*p && *p != '\n' && *p != '\r') {
            p++;
      }
      *p = 0;

      return line;
}

int playlist_add(playlist_t* pl, const ucs2_char_t* filename)
{
      pl->entries = (playlist_entry_t*)realloc(pl->entries, sizeof(playlist_entry_t) * (pl->num_entries+1));
      if (pl->entries) {
            ucs2cpy(pl->entries[pl->num_entries].filename, filename);
            pl->entries[pl->num_entries].order = pl->num_entries;
            pl->num_entries++;
            return 0;
      } else {
            return 1;
      }
}


int playlist_m3u_read(playlist_t* pl, const ucs2_char_t *filename)
{
      FILE *fp = ucs2fopen(filename, "r");
      if (!fp) {
            return -1;
      } else {
            char line[MAX_PATH * 8];
            pl->entries = 0;
            pl->num_entries = 0;

            while (fgets(line, sizeof(line)-1, fp) != NULL) {
                  strip(line);

                  if (line[0] == 0 || line[0] == '#') {
                        continue;
                  }

                  pl->entries = (playlist_entry_t*)realloc(pl->entries, sizeof(playlist_entry_t) * (pl->num_entries+1));
                  mbstoucs2(
                        pl->entries[pl->num_entries].filename,
                        sizeof(pl->entries[pl->num_entries].filename),
                        line,
                        strlen(line)+1
                        );
                  pl->num_entries++;
            }

            fclose(fp);
            return 0;
      }
}

int playlist_m3u8_read(playlist_t* pl, const ucs2_char_t *filename)
{
      FILE *fp = ucs2fopen(filename, "r");
      if (!fp) {
            return -1;
      } else {
            unsigned char *p = NULL;
            char line[MAX_PATH * 8];
            pl->entries = 0;
            pl->num_entries = 0;

            while (fgets(line, sizeof(line)-1, fp) != NULL) {
                  strip(line);

                  if (line[0] == 0 || line[0] == '#') {
                        continue;
                  }
                  p = (unsigned char *)line;
                  if (pl->entries == 0) {
                        /* Skip UTF-8 BOM if any. */
                        if (strlen((char *)p) > 3) {
                              if (p[0] == 0xEF && p[1] == 0xBB && p[2] == 0xBF) {
                                    p += 3; 
                              }
                        }
                  }

                  pl->entries = (playlist_entry_t*)realloc(pl->entries, sizeof(playlist_entry_t) * (pl->num_entries+1));
                  utf8toucs2(
                        pl->entries[pl->num_entries].filename,
                        sizeof(pl->entries[pl->num_entries].filename),
                        (char *)p,
                        strlen((char *)p)+1
                        );
                  pl->num_entries++;
            }

            fclose(fp);
            return 0;
      }
}

static int is_pls_entry(const char *line)
{
      return (tolower(line[0]) == 'f' && tolower(line[1]) == 'i' && tolower(line[2]) == 'l' && tolower(line[3]) == 'e');
}

static int strcmp_nocase(const char *x, const char *y)
{
      char a, b;

      do {
            a = tolower(*x);
            b = tolower(*y);
            if (!*x || !*y) {
                  break;
            }
            x++;
            y++;
      } while (a == b);
      return (a - b);
}

int playlist_pls_read(playlist_t* pl, const ucs2_char_t *filename)
{
      int is_pls = 0;
      FILE *fp = ucs2fopen(filename, "r");
      if (!fp) {
            return -1;
      } else {
            char line[MAX_PATH * 8];
            pl->entries = 0;
            pl->num_entries = 0;

            while (fgets(line, sizeof(line)-1, fp) != NULL) {
                  strip(line);

                  if (line[0] == 0) {
                        continue;
                  }

                  if (strcmp_nocase(line, "[playlist]") == 0) {
                        is_pls = 1;
                        continue;
                  }

                  if (is_pls && is_pls_entry(line)) {
                        char *p = NULL;
                        int number = strtol(line+4, &p, 10);
                        if (p && *p == '=') {
                              p++;
                              number--;   /* convert it to zero-based index. */
                              if (number <= pl->num_entries) {
                                    pl->entries = (playlist_entry_t*)realloc(pl->entries, sizeof(playlist_entry_t) * (number+1));
                                    pl->num_entries = number+1;
                              }
                              mbstoucs2(
                                    pl->entries[number].filename,
                                    sizeof(pl->entries[number].filename),
                                    p,
                                    strlen(p)+1
                                    );
                        }
                  }
            }

            fclose(fp);
            return 0;
      }
}

static int write_ucs2le(FILE *fp, const ucs2_char_t* str)
{
      int count = 0;

      for (;*str;str++) {
            uint8_t v[2];
            v[0] = *str & 0x00FF;
            v[1] = *str >> 8;
            if (fwrite(v, sizeof(uint8_t), 2, fp) != 2) {
                  break;
            }
            count++;
      }
      return count;
}

int playlist_plp_write(playlist_t* pl, const ucs2_char_t *filename)
{
      static const ucs2_char_t header1_str[] = {'P','L','P',' ','P','L','A','Y','L','I','S','T','\r','\n', 0};
      static const ucs2_char_t header2_str[] = {'V','E','R','S','I','O','N',' ','1','.','2','0','\r','\n', 0};
      static const ucs2_char_t entry_str[] = {'H','D','D',',',' ', 0};
      static const ucs2_char_t crlf_str[] = {'\r','\n', 0};
      
      FILE *fp = ucs2fopen(filename, "wb");
      if (!fp) {
            return -1;
      } else {
            int i;

            write_ucs2le(fp, header1_str);
            write_ucs2le(fp, header2_str);
            write_ucs2le(fp, crlf_str);

            for (i = 0;i < pl->num_entries;i++) {
                  if (pl->entries[i].filename[0]) {
                        ucs2_char_t filename[MAX_PATH];
                        ucs2cpy(filename, pl->entries[i].filename);


                        filepathutil_encode(filename);

                        write_ucs2le(fp, entry_str);
                        write_ucs2le(fp, filename);
                        write_ucs2le(fp, crlf_str);
                  }
            }

            write_ucs2le(fp, crlf_str);

            fclose(fp);

            return 0;
      }
}

static int comp_int(const void* _x, const void* _y)
{
      const playlist_entry_t* x = (const playlist_entry_t*)_x;
      const playlist_entry_t* y = (const playlist_entry_t*)_y;
      return ((x->order)>(y->order))-((x->order)<(y->order));
}

void playlist_shuffle(playlist_t* pl)
{
      int i;

      srand((unsigned int)time(NULL));
      for (i = 0;i < pl->num_entries;++i) {
            pl->entries[i].order = rand();
      }

      qsort(pl->entries, pl->num_entries, sizeof(playlist_entry_t), comp_int);
}

Generated by  Doxygen 1.6.0   Back to index