⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 playlist.c

📁 编译后直接运行的MP3播放器全部C语言源代码 一个包含FAT文件系统、系统引导 Boot、FLASH Driver等内容的
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************************************** *             __________               __   ___. *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  / *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  < *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \ *                     \/            \/     \/    \/            \/ * $Id: playlist.c,v 1.90 2004/01/29 05:37:54 hardeeps Exp $ * * Copyright (C) 2002 by wavey@wavey.org * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************//*    Dynamic playlist design (based on design originally proposed by ricII)    There are two files associated with a dynamic playlist:    1. Playlist file : This file contains the initial songs in the playlist.                       The file is created by the user and stored on the hard                       drive.  NOTE: If we are playing the contents of a                       directory, there will be no playlist file.    2. Control file :  This file is automatically created when a playlist is                       started and contains all the commands done to it.        The first non-comment line in a control file must begin with    "P:VERSION:DIR:FILE" where VERSION is the playlist control file version,    DIR is the directory where the playlist is located and FILE is the    playlist filename.  For dirplay, FILE will be empty.  An empty playlist    will have both entries as null.    Control file commands:        a. Add track (A:<position>:<last position>:<path to track>)            - Insert a track at the specified position in the current              playlist.  Last position is used to specify where last insertion              occurred.        b. Queue track (Q:<position>:<last position>:<path to track>)            - Queue a track at the specified position in the current              playlist.  Queued tracks differ from added tracks in that they              are deleted from the playlist as soon as they are played and              they are not saved to disk as part of the playlist.        c. Delete track (D:<position>)            - Delete track from specified position in the current playlist.        d. Shuffle playlist (S:<seed>:<index>)            - Shuffle entire playlist with specified seed.  The index              identifies the first index in the newly shuffled playlist              (needed for repeat mode).        e. Unshuffle playlist (U:<index>)            - Unshuffle entire playlist.  The index identifies the first index              in the newly unshuffled playlist.        f. Reset last insert position (R)            - Needed so that insertions work properly after resume  Resume:      The only resume info that needs to be saved is the current index in the      playlist and the position in the track.  When resuming, all the commands      in the control file will be reapplied so that the playlist indices are      exactly the same as before shutdown.  To avoid unnecessary disk      accesses, the shuffle mode settings are also saved in settings and only      flushed to disk when required. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include "playlist.h"#include "file.h"#include "dir.h"#include "sprintf.h"#include "debug.h"#include "mpeg.h"#include "lcd.h"#include "kernel.h"#include "settings.h"#include "status.h"#include "applimits.h"#include "screens.h"#include "buffer.h"#include "atoi.h"#include "misc.h"#include "button.h"#include "tree.h"#ifdef HAVE_LCD_BITMAP#include "icons.h"#include "widgets.h"#endif#include "lang.h"#define PLAYLIST_CONTROL_FILE ROCKBOX_DIR "/.playlist_control"#define PLAYLIST_CONTROL_FILE_VERSION 2/*    Each playlist index has a flag associated with it which identifies what    type of track it is.  These flags are stored in the 3 high order bits of    the index.        NOTE: This limits the playlist file size to a max of 512M.    Bits 31-30:        00 = Playlist track        01 = Track was prepended into playlist        10 = Track was inserted into playlist        11 = Track was appended into playlist    Bit 29:        0 = Added track        1 = Queued track */#define PLAYLIST_SEEK_MASK              0x1FFFFFFF#define PLAYLIST_INSERT_TYPE_MASK       0xC0000000#define PLAYLIST_QUEUE_MASK             0x20000000#define PLAYLIST_INSERT_TYPE_PREPEND    0x40000000#define PLAYLIST_INSERT_TYPE_INSERT     0x80000000#define PLAYLIST_INSERT_TYPE_APPEND     0xC0000000#define PLAYLIST_QUEUED                 0x20000000#define PLAYLIST_DISPLAY_COUNT          10static struct playlist_info current_playlist;static char now_playing[MAX_PATH+1];static void empty_playlist(struct playlist_info* playlist, bool resume);static void new_playlist(struct playlist_info* playlist, char *dir,                         char *file);static void create_control(struct playlist_info* playlist);static int  check_control(struct playlist_info* playlist);static void update_playlist_filename(struct playlist_info* playlist,                                     char *dir, char *file);static int add_indices_to_playlist(struct playlist_info* playlist,                                   char* buffer, int buflen);static int add_track_to_playlist(struct playlist_info* playlist,                                 char *filename, int position, bool queue,                                 int seek_pos);static int add_directory_to_playlist(struct playlist_info* playlist,                                     char *dirname, int *position, bool queue,                                     int *count, bool recurse);static int remove_track_from_playlist(struct playlist_info* playlist,                                      int position, bool write);static int randomise_playlist(struct playlist_info* playlist,                              unsigned int seed, bool start_current,                              bool write);static int sort_playlist(struct playlist_info* playlist, bool start_current,                         bool write);static int get_next_index(struct playlist_info* playlist, int steps);static void find_and_set_playlist_index(struct playlist_info* playlist,                                        unsigned int seek);static int compare(const void* p1, const void* p2);static int get_filename(struct playlist_info* playlist, int seek,                        bool control_file, char *buf, int buf_length);static int format_track_path(char *dest, char *src, int buf_length, int max,                             char *dir);static void display_playlist_count(int count, char *fmt);static void display_buffer_full(void);static int flush_pending_control(struct playlist_info* playlist);static int rotate_index(struct playlist_info* playlist, int index);/* * remove any files and indices associated with the playlist */static void empty_playlist(struct playlist_info* playlist, bool resume){    playlist->filename[0] = '\0';    if(playlist->fd >= 0)        /* If there is an already open playlist, close it. */        close(playlist->fd);    playlist->fd = -1;    if(playlist->control_fd >= 0)        close(playlist->control_fd);    playlist->control_fd = -1;    playlist->control_created = false;    playlist->in_ram = false;    if (playlist->buffer)        playlist->buffer[0] = 0;    playlist->buffer_end_pos = 0;    playlist->index = 0;    playlist->first_index = 0;    playlist->amount = 0;    playlist->last_insert_pos = -1;    playlist->seed = 0;    playlist->shuffle_modified = false;    playlist->deleted = false;    playlist->num_inserted_tracks = 0;    playlist->shuffle_flush = false;    if (!resume && playlist->current)    {        /* start with fresh playlist control file when starting new           playlist */        create_control(playlist);        /* Reset resume settings */        global_settings.resume_first_index = 0;        global_settings.resume_seed = -1;    }}/* * Initialize a new playlist for viewing/editing/playing.  dir is the * directory where the playlist is located and file is the filename. */static void new_playlist(struct playlist_info* playlist, char *dir,                         char *file){    empty_playlist(playlist, false);    if (!file)    {        file = "";        if (dir && playlist->current) /* !current cannot be in_ram */            playlist->in_ram = true;        else            dir = ""; /* empty playlist */    }        update_playlist_filename(playlist, dir, file);    if (playlist->control_fd >= 0)    {        if (fprintf(playlist->control_fd, "P:%d:%s:%s\n",            PLAYLIST_CONTROL_FILE_VERSION, dir, file) > 0)            fsync(playlist->control_fd);        else            splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR));    }}/* * create control file for playlist */static void create_control(struct playlist_info* playlist){    playlist->control_fd = creat(playlist->control_filename, 0000200);    if (playlist->control_fd < 0)        splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_ACCESS_ERROR));    playlist->control_created = true;}/* * validate the control file.  This may include creating/initializing it if * necessary; */static int check_control(struct playlist_info* playlist){    if (!playlist->control_created)    {        create_control(playlist);        if (playlist->control_fd >= 0)        {            char* dir = playlist->filename;            char* file = playlist->filename+playlist->dirlen;            char c = playlist->filename[playlist->dirlen-1];            playlist->filename[playlist->dirlen-1] = '\0';            if (fprintf(playlist->control_fd, "P:%d:%s:%s\n",                PLAYLIST_CONTROL_FILE_VERSION, dir, file) > 0)                fsync(playlist->control_fd);            else                splash(HZ*2, true, str(LANG_PLAYLIST_CONTROL_UPDATE_ERROR));            playlist->filename[playlist->dirlen-1] = c;        }    }    if (playlist->control_fd < 0)        return -1;    return 0;}/* * store directory and name of playlist file */static void update_playlist_filename(struct playlist_info* playlist,                                     char *dir, char *file){    char *sep="";    int dirlen = strlen(dir);        /* If the dir does not end in trailing slash, we use a separator.       Otherwise we don't. */    if('/' != dir[dirlen-1])    {        sep="/";        dirlen++;    }        playlist->dirlen = dirlen;        snprintf(playlist->filename, sizeof(playlist->filename),        "%s%s%s",         dir, sep, file);}/* * calculate track offsets within a playlist file */static int add_indices_to_playlist(struct playlist_info* playlist,                                   char* buffer, int buflen){    unsigned int nread;    unsigned int i = 0;    unsigned int count = 0;    bool store_index;    unsigned char *p;    if(-1 == playlist->fd)        playlist->fd = open(playlist->filename, O_RDONLY);    if(playlist->fd < 0)        return -1; /* failure */    #ifdef HAVE_LCD_BITMAP    if(global_settings.statusbar)        lcd_setmargins(0, STATUSBAR_HEIGHT);    else        lcd_setmargins(0, 0);#endif    splash(0, true, str(LANG_PLAYLIST_LOAD));    if (!buffer)    {        /* use mp3 buffer for maximum load speed */        mpeg_stop();        buffer = mp3buf;        buflen = (mp3end - mp3buf);            }        store_index = true;    while(1)    {        nread = read(playlist->fd, buffer, buflen);        /* Terminate on EOF */        if(nread <= 0)            break;                p = buffer;        for(count=0; count < nread; count++,p++) {            /* Are we on a new line? */            if((*p == '\n') || (*p == '\r'))            {                store_index = true;            }             else if(store_index)             {                store_index = false;                if(*p != '#')                {                    /* Store a new entry */                    playlist->indices[ playlist->amount ] = i+count;                    playlist->amount++;                    if ( playlist->amount >= playlist->max_playlist_size ) {                        display_buffer_full();                        return -1;                    }                }            }        }        i+= count;    }    return 0;}/* * Add track to playlist at specified position.  There are three special * positions that can be specified: *     PLAYLIST_PREPEND      - Add track at beginning of playlist *     PLAYLIST_INSERT       - Add track after current song.  NOTE: If there *                             are already inserted tracks then track is added *                             to the end of the insertion list. *     PLAYLIST_INSERT_FIRST - Add track immediately after current song, no *                             matter what other tracks have been inserted. *     PLAYLIST_INSERT_LAST  - Add track to end of playlist */static int add_track_to_playlist(struct playlist_info* playlist,                                 char *filename, int position, bool queue,                                 int seek_pos){    int insert_position = position;    unsigned int flags = PLAYLIST_INSERT_TYPE_INSERT;    int i;    if (playlist->amount >= playlist->max_playlist_size)    {        display_buffer_full();        return -1;    }    switch (position)    {        case PLAYLIST_PREPEND:            insert_position = playlist->first_index;            flags = PLAYLIST_INSERT_TYPE_PREPEND;            break;        case PLAYLIST_INSERT:            /* if there are already inserted tracks then add track to end of               insertion list else add after current playing track */            if (playlist->last_insert_pos >= 0 &&                playlist->last_insert_pos < playlist->amount &&                (playlist->indices[playlist->last_insert_pos]&                    PLAYLIST_INSERT_TYPE_MASK) == PLAYLIST_INSERT_TYPE_INSERT)                position = insert_position = playlist->last_insert_pos+1;            else if (playlist->amount > 0)                position = insert_position = playlist->index + 1;            else                position = insert_position = 0;            playlist->last_insert_pos = position;            break;        case PLAYLIST_INSERT_FIRST:            if (playlist->amount > 0)                position = insert_position = playlist->index + 1;            else                position = insert_position = 0;            if (playlist->last_insert_pos < 0)                playlist->last_insert_pos = position;            break;        case PLAYLIST_INSERT_LAST:            if (playlist->first_index > 0)                insert_position = playlist->first_index;            else                insert_position = playlist->amount;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -