diff options
-rw-r--r-- | DOCS/OUTDATED-tech/playtree | 123 | ||||
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | asxparser.c | 207 | ||||
-rw-r--r-- | asxparser.h | 56 | ||||
-rw-r--r-- | command.c | 154 | ||||
-rw-r--r-- | etc/input.conf | 14 | ||||
-rw-r--r-- | input/input.c | 32 | ||||
-rw-r--r-- | input/input.h | 10 | ||||
-rw-r--r-- | libvo/video_out.c | 5 | ||||
-rw-r--r-- | m_config.c | 225 | ||||
-rw-r--r-- | m_config.h | 43 | ||||
-rw-r--r-- | mp_core.h | 18 | ||||
-rw-r--r-- | mpcommon.h | 24 | ||||
-rw-r--r-- | mplayer.c | 326 | ||||
-rw-r--r-- | osdep/macosx_finder_args.h | 6 | ||||
-rw-r--r-- | osdep/macosx_finder_args.m | 32 | ||||
-rw-r--r-- | parser-mpcmd.c | 198 | ||||
-rw-r--r-- | parser-mpcmd.h | 6 | ||||
-rw-r--r-- | playlist.c | 185 | ||||
-rw-r--r-- | playlist.h | 67 | ||||
-rw-r--r-- | playlist_parser.c (renamed from playtreeparser.c) | 399 | ||||
-rw-r--r-- | playlist_parser.h | 34 | ||||
-rw-r--r-- | playtree.c | 908 | ||||
-rw-r--r-- | playtree.h | 302 | ||||
-rw-r--r-- | playtreeparser.h | 73 |
25 files changed, 914 insertions, 2537 deletions
diff --git a/DOCS/OUTDATED-tech/playtree b/DOCS/OUTDATED-tech/playtree deleted file mode 100644 index 2aaf5a175e..0000000000 --- a/DOCS/OUTDATED-tech/playtree +++ /dev/null @@ -1,123 +0,0 @@ - -How work the playtree ? - -Good question, I try to explain but note that it's the first doc -I write :) - -First there is two things. The playtree itself and the iterator. -The playtree represent the data and the iterator is used by -mplayer to go from entry to entry. - -First the play_tree struct : - - -struct play_tree { - play_tree_t* parent; - play_tree_t* child; - play_tree_t* next; - play_tree_t* prev; - - play_tree_param_t* params; - int loop; - char** files; - int entry_type; -}; - -The play_tree_t* hold the links in the 4 directions, the params hold -all parameters of this entry, loop is obvious (loop < 0 mean infint loop), -files hold all the files of this entry and entry_type obviously tell the -type of this entry (Node, file, dvd, vcd ot tv). - -An entry can hold more than one file, why ? - -Because an entry can be a network stream and usually you have more than -one server. But all send the same thing, so it's only on entry with sevral -sources. - -Then how do I use this stuff ? - -First you create an entry using the play_tree_new func. This create the struct -and fill it with defaults values. -Then this can become a node or a leaf. It will become a node as soon as you link it -to another one using either play_tree_set_child or play_tree_set_parent. -Or it will become a leaf as soon as you use play_tree_add_file on it. -If an entry contain at least one file it can't become an node (an assert will be -raised) and if en entry has a child you can't add file to (here also an assert will -be raised). -Then to create a list of entry you should use play_tree_append_entry, -play_tree_prepend_entry or play_tree_insert_entry. -In all this function you can use any entry of the the list as first argument, -no need that it's the first one. The same apply when you set the child of a node, -the child argument can be any entry in a list. -To remove an entry from the tree use play_tree_remove. If the second arg (free_it) -is true it will also free it, if the entry should be freed and the third -arg is true it will also free the children. - -When your tree is ready you can then use play_tree_cleanup to remove all unuseful -entries. - -If you want to load a playlist you can use parse_playtree which take a stream_t -as argument or parse_playlist_file which take a filename as argument. -Both function will return NULL in case of failure or a new (cleaned) tree that -you can add somewhere in your tree. - -How do I add DVD, VCD or TV entry to the tree ? - -You should use some virtual URL as filename like : - dvd://x where x is the title number. - vcd://x where x is the track number - tv://x where x is the channel - - -My playtree is ready now, what with this play_tree_iter ? - -This is an iterator used to go trough the tree. It handle itself -loop of list and setting mplayer config according to the params -of each entry. -It's created with play_tree_iter_new which take as argument a play_tree_t -and an m_config_t which is then used to set/unset the params of each entry. -After creation the iter point to nothing, you should init with a first step. -To go to another entry in the list you should use play_tree_iter_step. The -second argument is the direction of the step : positive value go frontward, -negative go backward and 0 don't move. The third tell if must care of -node or not. If it's true, the iterator will stop on nodes, otherwise it go -to the next valid entry. -This function return different values : -PLAY_TREE_ITER_ERROR : obvious -PLAY_TREE_ITER_ENTRY : we are now on an entry -PLAY_TREE_ITER_NODE : we are now on a node -PLAY_TREE_ITER_END : we are now at end -(( Note : I must add a PLAY_TREE_ITER_BEGINNING for the beginning. Don't know -what it will return in a such case. PLAY_TREE_ITER_ERROR ? )) - -There is also play_tree_iter_up_step which can be used to break a loop or skip -the current list. The argument are the same than play_tree_iter_step. The -difference is that it go back to parent of the current list, and then step according -to the arguments. - -Then when your iter returned PLAY_TREE_ITER_ENTRY you can use -play_tree_iter_get_file to get the file. If you call it more than one time -it will return the next file for this entry or loop trough the list if no more -file are available. You can now how many files are available using -iter->num_files and which one it returned using iter->file. -In case the entry is a DVD, VCD or TV channel the returned string is not a filename -but "DVD title x", "VCD track x" or "TV channel x". -To distinc those case from a normal file you can check iter->tree->entry_type. -It will contain one of PLAY_TREE_ENTRY_DVD, PLAY_TREE_ENTRY_VCD, -PLAY_TREE_ENTRY_TV or PLAY_TREE_ENTRY_FILE. - -If you need to make some check with the iter, such as will next entry be valid, etc -You must create a clone with play_tree_iter_new_copy. This iter will not affect -the config, so you can do all you want with it. - -Then when you have finish with the iter free it with play_tree_iter_free. - - -Ok, that's all for now. To have some exemples look into mplayer.c ;) -First just after config parsing, the iterator is created there. Also -after stream opening, in case the stream is a playlist it replace the -entry which contained the playlist by the result of the parsing. -In the event handling it check if a step can be done, etc. And finnaly -at the end it go the next entry. - -Suggestion, flames, etc about this doc must go to albeu@free.fr @@ -218,8 +218,8 @@ SRCS_COMMON = asxparser.c \ mpcommon.c \ parser-cfg.c \ path.c \ - playtree.c \ - playtreeparser.c \ + playlist.c \ + playlist_parser.c \ subopt-helper.c \ talloc.c \ libaf/af.c \ diff --git a/asxparser.c b/asxparser.c index 5d0d811ab4..89cf7bd1a1 100644 --- a/asxparser.c +++ b/asxparser.c @@ -24,13 +24,62 @@ #include <string.h> #include <unistd.h> -#include "playtree.h" -#include "playtreeparser.h" +#include "playlist.h" +#include "playlist_parser.h" #include "stream/stream.h" #include "libmpdemux/demuxer.h" #include "asxparser.h" #include "mp_msg.h" -#include "m_config.h" + + +typedef struct ASX_Parser_t ASX_Parser_t; + +typedef struct { + char* buffer; + int line; +} ASX_LineSave_t; + +struct ASX_Parser_t { + int line; // Curent line + ASX_LineSave_t *ret_stack; + int ret_stack_size; + char* last_body; + int deep; + struct playlist *pl; +}; + +ASX_Parser_t *asx_parser_new(struct playlist *pl); + +void +asx_parser_free(ASX_Parser_t* parser); + +/* + * Return -1 on error, 0 when nothing is found, 1 on sucess + */ +int +asx_get_element(ASX_Parser_t* parser,char** _buffer, + char** _element,char** _body,char*** _attribs); + +int +asx_parse_attribs(ASX_Parser_t* parser,char* buffer,char*** _attribs); + +/////// Attribs utils + +char* +asx_get_attrib(const char* attrib,char** attribs); + +int +asx_attrib_to_enum(const char* val,char** valid_vals); + +#define asx_free_attribs(a) asx_list_free(&a,free) + +////// List utils + +typedef void (*ASX_FreeFunc)(void* arg); + +void +asx_list_free(void* list_ptr,ASX_FreeFunc free_func); + ////// List utils @@ -77,11 +126,10 @@ asx_attrib_to_enum(const char* val,char** valid_vals) { #define asx_warning_attrib_required(p,e,a) mp_msg(MSGT_PLAYTREE,MSGL_WARN,"At line %d : element %s don't have the required attribute %s",p->line,e,a) #define asx_warning_body_parse_error(p,e) mp_msg(MSGT_PLAYTREE,MSGL_WARN,"At line %d : error while parsing %s body",p->line,e) -ASX_Parser_t* -asx_parser_new(struct m_config *mconfig) +ASX_Parser_t *asx_parser_new(struct playlist *pl) { ASX_Parser_t* parser = calloc(1,sizeof(ASX_Parser_t)); - parser->mconfig = mconfig; + parser->pl = pl; return parser; } @@ -388,7 +436,7 @@ asx_get_element(ASX_Parser_t* parser,char** _buffer, } static void -asx_parse_ref(ASX_Parser_t* parser, char** attribs, play_tree_t* pt) { +asx_parse_ref(ASX_Parser_t* parser, char** attribs) { char *href; href = asx_get_attrib("HREF",attribs); @@ -409,7 +457,7 @@ asx_parse_ref(ASX_Parser_t* parser, char** attribs, play_tree_t* pt) { } #endif - play_tree_add_file(pt,href); + playlist_add_file(parser->pl, href); mp_msg(MSGT_PLAYTREE,MSGL_V,"Adding file %s to element entry\n",href); @@ -417,212 +465,137 @@ asx_parse_ref(ASX_Parser_t* parser, char** attribs, play_tree_t* pt) { } -static play_tree_t* -asx_parse_entryref(ASX_Parser_t* parser,char* buffer,char** _attribs) { - play_tree_t* pt; +static void asx_parse_entryref(ASX_Parser_t* parser,char* buffer,char** _attribs) { char *href; stream_t* stream; - play_tree_parser_t* ptp; int f=DEMUXER_TYPE_UNKNOWN; if(parser->deep > 0) - return NULL; + return; href = asx_get_attrib("HREF",_attribs); if(href == NULL) { asx_warning_attrib_required(parser,"ENTRYREF" ,"HREF" ); - return NULL; + return; } stream=open_stream(href,0,&f); if(!stream) { mp_msg(MSGT_PLAYTREE,MSGL_WARN,"Can't open playlist %s\n",href); free(href); - return NULL; + return; } - mp_msg(MSGT_PLAYTREE,MSGL_V,"Adding playlist %s to element entryref\n",href); - - ptp = play_tree_parser_new(stream, parser->mconfig, parser->deep+1); - - pt = play_tree_parser_get_play_tree(ptp, 1); + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Not recursively loading playlist %s\n",href); - play_tree_parser_free(ptp); free_stream(stream); free(href); //mp_msg(MSGT_PLAYTREE,MSGL_INFO,"Need to implement entryref\n"); - - return pt; } -static play_tree_t* -asx_parse_entry(ASX_Parser_t* parser,char* buffer,char** _attribs) { +static void asx_parse_entry(ASX_Parser_t* parser,char* buffer,char** _attribs) { char *element,*body,**attribs; - int r,nref=0; - play_tree_t *ref; - - ref = play_tree_new(); + int r; while(buffer && buffer[0] != '\0') { r = asx_get_element(parser,&buffer,&element,&body,&attribs); if(r < 0) { asx_warning_body_parse_error(parser,"ENTRY"); - return NULL; + return; } else if (r == 0) { // No more element break; } if(strcasecmp(element,"REF") == 0) { - asx_parse_ref(parser,attribs,ref); + asx_parse_ref(parser,attribs); mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to entry\n",element); - nref++; } else mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Ignoring element %s\n",element); free(body); asx_free_attribs(attribs); } - if(nref <= 0) { - play_tree_free(ref,1); - return NULL; - } - return ref; - } -static play_tree_t* -asx_parse_repeat(ASX_Parser_t* parser,char* buffer,char** _attribs) { +static void asx_parse_repeat(ASX_Parser_t* parser,char* buffer,char** _attribs) { char *element,*body,**attribs; - play_tree_t *repeat, *list=NULL, *entry; - char* count; int r; - repeat = play_tree_new(); - - count = asx_get_attrib("COUNT",_attribs); - if(count == NULL) { - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Setting element repeat loop to infinit\n"); - repeat->loop = -1; // Infinit - } else { - repeat->loop = atoi(count); - free(count); - if(repeat->loop == 0) repeat->loop = 1; - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Setting element repeat loop to %d\n",repeat->loop); - } + asx_get_attrib("COUNT",_attribs); + mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Ignoring repeated playlist entries\n"); while(buffer && buffer[0] != '\0') { r = asx_get_element(parser,&buffer,&element,&body,&attribs); if(r < 0) { asx_warning_body_parse_error(parser,"REPEAT"); - return NULL; + return; } else if (r == 0) { // No more element break; } if(strcasecmp(element,"ENTRY") == 0) { - entry = asx_parse_entry(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to repeat\n",element); - } + asx_parse_entry(parser,body,attribs); } else if(strcasecmp(element,"ENTRYREF") == 0) { - entry = asx_parse_entryref(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to repeat\n",element); - } + asx_parse_entryref(parser,body,attribs); } else if(strcasecmp(element,"REPEAT") == 0) { - entry = asx_parse_repeat(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to repeat\n",element); - } + asx_parse_repeat(parser,body,attribs); } else mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Ignoring element %s\n",element); free(body); asx_free_attribs(attribs); } - if(!list) { - play_tree_free(repeat,1); - return NULL; - } - play_tree_set_child(repeat,list); - - return repeat; - } - -play_tree_t* -asx_parser_build_tree(struct m_config *mconfig, char* buffer,int deep) { +bool asx_parse(char* buffer, struct playlist *pl) +{ char *element,*asx_body,**asx_attribs,*body = NULL, **attribs; int r; - play_tree_t *asx,*entry,*list = NULL; - ASX_Parser_t* parser = asx_parser_new(mconfig); + ASX_Parser_t* parser = asx_parser_new(pl); parser->line = 1; - parser->deep = deep; + parser->deep = 0; r = asx_get_element(parser,&buffer,&element,&asx_body,&asx_attribs); if(r < 0) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"At line %d : Syntax error ???",parser->line); asx_parser_free(parser); - return NULL; + return false; } else if(r == 0) { // No contents mp_msg(MSGT_PLAYTREE,MSGL_ERR,"empty asx element"); asx_parser_free(parser); - return NULL; + return false; } if(strcasecmp(element,"ASX") != 0) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"first element isn't ASX, it's %s\n",element); asx_free_attribs(asx_attribs); asx_parser_free(parser); - return NULL; + return false; } if(!asx_body) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"ASX element is empty"); asx_free_attribs(asx_attribs); asx_parser_free(parser); - return NULL; + return false; } - asx = play_tree_new(); buffer = asx_body; while(buffer && buffer[0] != '\0') { r = asx_get_element(parser,&buffer,&element,&body,&attribs); if(r < 0) { asx_warning_body_parse_error(parser,"ASX"); asx_parser_free(parser); - return NULL; + return false; } else if (r == 0) { // No more element break; } if(strcasecmp(element,"ENTRY") == 0) { - entry = asx_parse_entry(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to asx\n",element); - } + asx_parse_entry(parser,body,attribs); } else if(strcasecmp(element,"ENTRYREF") == 0) { - entry = asx_parse_entryref(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to asx\n",element); - } + asx_parse_entryref(parser,body,attribs); } else if(strcasecmp(element,"REPEAT") == 0) { - entry = asx_parse_repeat(parser,body,attribs); - if(entry) { - if(!list) list = entry; - else play_tree_append_entry(list,entry); - mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Adding element %s to asx\n",element); - } + asx_parse_repeat(parser,body,attribs); } else mp_msg(MSGT_PLAYTREE,MSGL_DBG2,"Ignoring element %s\n",element); free(body); @@ -632,15 +605,5 @@ asx_parser_build_tree(struct m_config *mconfig, char* buffer,int deep) { free(asx_body); asx_free_attribs(asx_attribs); asx_parser_free(parser); - - - if(!list) { - play_tree_free(asx,1); - - return NULL; - } - - play_tree_set_child(asx,list); - - return asx; + return true; } diff --git a/asxparser.h b/asxparser.h index 57577101fb..e49a2cedc0 100644 --- a/asxparser.h +++ b/asxparser.h @@ -19,59 +19,9 @@ #ifndef MPLAYER_ASXPARSER_H #define MPLAYER_ASXPARSER_H -#include "playtree.h" +#include <stdbool.h> -typedef struct ASX_Parser_t ASX_Parser_t; - -typedef struct { - char* buffer; - int line; -} ASX_LineSave_t; - -struct ASX_Parser_t { - int line; // Curent line - ASX_LineSave_t *ret_stack; - int ret_stack_size; - char* last_body; - int deep; - struct m_config *mconfig; -}; - -struct m_config; -ASX_Parser_t* -asx_parser_new(struct m_config *mconfig); - -void -asx_parser_free(ASX_Parser_t* parser); - -/* - * Return -1 on error, 0 when nothing is found, 1 on sucess - */ -int -asx_get_element(ASX_Parser_t* parser,char** _buffer, - char** _element,char** _body,char*** _attribs); - -int -asx_parse_attribs(ASX_Parser_t* parser,char* buffer,char*** _attribs); - -/////// Attribs utils - -char* -asx_get_attrib(const char* attrib,char** attribs); - -int -asx_attrib_to_enum(const char* val,char** valid_vals); - -#define asx_free_attribs(a) asx_list_free(&a,free) - -////// List utils - -typedef void (*ASX_FreeFunc)(void* arg); - -void -asx_list_free(void* list_ptr,ASX_FreeFunc free_func); - -play_tree_t* -asx_parser_build_tree(struct m_config *mconfig, char* buffer, int ref); +struct playlist; +bool asx_parse(char* buffer, struct playlist *pl); #endif /* MPLAYER_ASXPARSER_H */ @@ -32,6 +32,8 @@ #include "libmpdemux/stheader.h" #include "codec-cfg.h" #include "mplayer.h" +#include "playlist.h" +#include "playlist_parser.h" #include "sub/sub.h" #include "sub/dec_sub.h" #include "m_option.h" @@ -43,7 +45,7 @@ #include "mp_osd.h" #include "libvo/video_out.h" #include "libvo/csputils.h" -#include "playtree.h" +#include "playlist.h" #include "libao2/audio_out.h" #include "mpcommon.h" #include "mixer.h" @@ -2771,28 +2773,6 @@ static void remove_subtitle_range(MPContext *mpctx, int start, int count) } } -static void do_clear_pt(struct play_tree *node, struct play_tree *exclude) -{ - while (node) { - do_clear_pt(node->child, exclude); - struct play_tree *next = node->next; - // do not delete root node, or nodes that could lead to "exclude" node - if (node->parent && !node->child && node != exclude) - play_tree_remove(node, 1, 1); - node = next; - } -} - -static void clear_play_tree(MPContext *mpctx) -{ - struct play_tree *exclude = NULL; - if (mpctx->playtree_iter) { - assert(mpctx->playtree == mpctx->playtree_iter->root); - exclude = mpctx->playtree_iter->tree; - } - do_clear_pt(mpctx->playtree, exclude); -} - static char *format_time(double time) { int h, m, s = time; @@ -3085,54 +3065,21 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) exit_player_with_rc(mpctx, EXIT_QUIT, (cmd->nargs > 0) ? cmd->args[0].v.i : 0); - case MP_CMD_PLAY_TREE_STEP: { - int n = cmd->args[0].v.i == 0 ? 1 : cmd->args[0].v.i; - int force = cmd->args[1].v.i; - - { - if (!force && mpctx->playtree_iter) { - play_tree_iter_t *i = - play_tree_iter_new_copy(mpctx->playtree_iter); - if (play_tree_iter_step(i, n, 0) == - PLAY_TREE_ITER_ENTRY) - mpctx->stop_play = - (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; - play_tree_iter_free(i); - } else - mpctx->stop_play = (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; - if (mpctx->stop_play) - mpctx->play_tree_step = n; - } - break; - } - - case MP_CMD_PLAY_TREE_UP_STEP: { - int n = cmd->args[0].v.i > 0 ? 1 : -1; - int force = cmd->args[1].v.i; + case MP_CMD_PLAYLIST_NEXT: + case MP_CMD_PLAYLIST_PREV: + { + int dir = cmd->id == MP_CMD_PLAYLIST_PREV ? -1 : +1; + int force = cmd->args[0].v.i; - if (!force && mpctx->playtree_iter) { - play_tree_iter_t *i = - play_tree_iter_new_copy(mpctx->playtree_iter); - if (play_tree_iter_up_step(i, n, 0) == PLAY_TREE_ITER_ENTRY) - mpctx->stop_play = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; - play_tree_iter_free(i); - } else - mpctx->stop_play = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; + struct playlist_entry *e = playlist_get_next(mpctx->playlist, dir); + if (!e && !force) + break; + mpctx->playlist->current = e; + mpctx->playlist->current_was_replaced = false; + mpctx->stop_play = PT_CURRENT_ENTRY; break; } - case MP_CMD_PLAY_ALT_SRC_STEP: - if (mpctx->playtree_iter && mpctx->playtree_iter->num_files > 1) { - int v = cmd->args[0].v.i; - if (v > 0 - && mpctx->playtree_iter->file < - mpctx->playtree_iter->num_files) - mpctx->stop_play = PT_NEXT_SRC; - else if (v < 0 && mpctx->playtree_iter->file > 1) - mpctx->stop_play = PT_PREV_SRC; - } - break; - case MP_CMD_SUB_STEP: if (sh_video) { int movement = cmd->args[0].v.i; @@ -3198,56 +3145,59 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) } case MP_CMD_LOADFILE: { - play_tree_t *e = play_tree_new(); - play_tree_add_file(e, cmd->args[0].v.s); + char *filename = cmd->args[0].v.s; + bool append = cmd->args[1].v.i; - if (cmd->args[1].v.i) // append - play_tree_append_entry(mpctx->playtree->child, e); - else { - // Go back to the starting point. - while (play_tree_iter_up_step(mpctx->playtree_iter, 0, 1) - != PLAY_TREE_ITER_END) - /* NOP */; - play_tree_free_list(mpctx->playtree->child, 1); - play_tree_set_child(mpctx->playtree, e); - pt_iter_goto_head(mpctx->playtree_iter); - mpctx->stop_play = PT_NEXT_SRC; + if (!append) + playlist_clear(mpctx->playlist); + + playlist_add(mpctx->playlist, playlist_entry_new(filename)); + + if (!append) { + mpctx->playlist->current = mpctx->playlist->first; + mpctx->playlist->current_was_replaced = false; + mpctx->stop_play = PT_CURRENT_ENTRY; } break; } case MP_CMD_LOADLIST: { - play_tree_t *e = parse_playlist_file(mpctx->mconfig, - bstr0(cmd->args[0].v.s)); - if (!e) + char *filename = cmd->args[0].v.s; + bool append = cmd->args[1].v.i; + struct playlist *pl = playlist_parse_file(filename); + if (!pl) { + if (!append) + playlist_clear(mpctx->playlist); + playlist_transfer_entries(mpctx->playlist, pl); + talloc_free(pl); + + if (!append) + mpctx->stop_play = PT_NEXT_ENTRY; + } else { mp_tmsg(MSGT_CPLAYER, MSGL_ERR, - "\nUnable to load playlist %s.\n", cmd->args[0].v.s); - else { - if (cmd->args[1].v.i) // append - play_tree_append_entry(mpctx->playtree->child, e); - else { - // Go back to the starting point. - while (play_tree_iter_up_step(mpctx->playtree_iter, 0, 1) - != PLAY_TREE_ITER_END) - /* NOP */; - play_tree_free_list(mpctx->playtree->child, 1); - play_tree_set_child(mpctx->playtree, e); - pt_iter_goto_head(mpctx->playtree_iter); - mpctx->stop_play = PT_NEXT_SRC; - } + "\nUnable to load playlist %s.\n", filename); } break; } - case MP_CMD_PLAY_TREE_CLEAR: - clear_play_tree(mpctx); + case MP_CMD_PLAYLIST_CLEAR: { + // Supposed to clear the playlist, except the currently played item. + if (mpctx->playlist->current_was_replaced) + mpctx->playlist->current = NULL; + while (mpctx->playlist->first) { + struct playlist_entry *e = mpctx->playlist->first; + if (e == mpctx->playlist->current) { + e = e->next; + if (!e) + break; + } + playlist_remove(mpctx->playlist, e); + } break; + } case MP_CMD_STOP: // Go back to the starting point. - while (play_tree_iter_up_step(mpctx->playtree_iter, 0, 1) != - PLAY_TREE_ITER_END) - /* NOP */; mpctx->stop_play = PT_STOP; break; diff --git a/etc/input.conf b/etc/input.conf index 46bc17d500..0bfc5ca607 100644 --- a/etc/input.conf +++ b/etc/input.conf @@ -57,13 +57,9 @@ ESC quit p pause # toggle pause/playback mode . frame_step # advance one frame and pause SPACE pause -HOME pt_up_step 1 -END pt_up_step -1 -> pt_step 1 # skip to next file -ENTER pt_step 1 1 # skip to next file or quit -< pt_step -1 # skip to previous file -INS alt_src_step 1 -DEL alt_src_step -1 +> playlist_next # skip to next file +ENTER playlist_next 1 # skip to next file or quit +< playlist_prev # skip to previous file o osd # cycle through OSD mode I osd_show_property_text "${filename}" # display filename in osd P osd_show_progression @@ -121,8 +117,8 @@ PLAYPAUSE pause STOP quit FORWARD seek 60 REWIND seek -60 -NEXT pt_step 1 -PREV pt_step -1 +NEXT playlist_next +PREV playlist_prev VOLUME_UP volume 1 VOLUME_DOWN volume -1 MUTE mute diff --git a/input/input.c b/input/input.c index dbc29d964f..836c9df14a 100644 --- a/input/input.c +++ b/input/input.c @@ -108,9 +108,8 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_STOP, "stop", }, { MP_CMD_PAUSE, "pause", }, { MP_CMD_FRAME_STEP, "frame_step", }, - { MP_CMD_PLAY_TREE_STEP, "pt_step", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_PLAY_TREE_UP_STEP, "pt_up_step", { ARG_INT, OARG_INT(0) } }, - { MP_CMD_PLAY_ALT_SRC_STEP, "alt_src_step", { ARG_INT } }, + { MP_CMD_PLAYLIST_NEXT, "playlist_next", { OARG_INT(0) } }, + { MP_CMD_PLAYLIST_PREV, "playlist_prev", { OARG_INT(0) } }, { MP_CMD_LOOP, "loop", { ARG_INT, OARG_INT(0) } }, { MP_CMD_SUB_DELAY, "sub_delay", { ARG_FLOAT, OARG_INT(0) } }, { MP_CMD_SUB_STEP, "sub_step", { ARG_INT, OARG_INT(0) } }, @@ -193,7 +192,7 @@ static const mp_cmd_t mp_cmds[] = { { MP_CMD_SWITCH_VSYNC, "switch_vsync", { OARG_INT(0) } }, { MP_CMD_LOADFILE, "loadfile", { ARG_STRING, OARG_INT(0) } }, { MP_CMD_LOADLIST, "loadlist", { ARG_STRING, OARG_INT(0) } }, - { MP_CMD_PLAY_TREE_CLEAR, "pt_clear", }, + { MP_CMD_PLAYLIST_CLEAR, "playlist_clear", }, { MP_CMD_RUN, "run", { ARG_STRING } }, { MP_CMD_CAPTURING, "capturing", }, { MP_CMD_VF_CHANGE_RECTANGLE, "change_rectangle", { ARG_INT, ARG_INT } }, @@ -444,13 +443,9 @@ static const struct cmd_bind def_cmd_binds[] = { { { 'p', 0 }, "pause" }, { { ' ', 0 }, "pause" }, { { '.', 0 }, "frame_step" }, - { { KEY_HOME, |