summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/OUTDATED-tech/playtree123
-rw-r--r--Makefile4
-rw-r--r--asxparser.c207
-rw-r--r--asxparser.h56
-rw-r--r--command.c154
-rw-r--r--etc/input.conf14
-rw-r--r--input/input.c32
-rw-r--r--input/input.h10
-rw-r--r--libvo/video_out.c5
-rw-r--r--m_config.c225
-rw-r--r--m_config.h43
-rw-r--r--mp_core.h18
-rw-r--r--mpcommon.h24
-rw-r--r--mplayer.c326
-rw-r--r--osdep/macosx_finder_args.h6
-rw-r--r--osdep/macosx_finder_args.m32
-rw-r--r--parser-mpcmd.c198
-rw-r--r--parser-mpcmd.h6
-rw-r--r--playlist.c185
-rw-r--r--playlist.h67
-rw-r--r--playlist_parser.c (renamed from playtreeparser.c)399
-rw-r--r--playlist_parser.h34
-rw-r--r--playtree.c908
-rw-r--r--playtree.h302
-rw-r--r--playtreeparser.h73
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
diff --git a/Makefile b/Makefile
index 01c4d59305..f3209ff528 100644
--- a/Makefile
+++ b/Makefile
@@ -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 */
diff --git a/command.c b/command.c
index d90d3ee76b..72f978d3be 100644
--- a/command.c
+++ b/command.c
@@ -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, 0 }, "pt_up_step 1" },
- { { KEY_END, 0 }, "pt_up_step -1" },
- { { '>', 0 }, "pt_step 1" },
- { { KEY_ENTER, 0 }, "pt_step 1 1" },
- { { '<', 0 }, "pt_step -1" },
- { { KEY_INS, 0 }, "alt_src_step 1" },
- { { KEY_DEL, 0 }, "alt_src_step -1" },
+ { { '>', 0 }, "playlist_next" },
+ { { KEY_ENTER, 0 }, "playlist_next 1" },
+ { { '<', 0 }, "playlist_prev" },
{ { 'o', 0 }, "osd" },
{ { 'I', 0 }, "osd_show_property_text \"${filename}\"" },
{ { 'P', 0 }, "osd_show_progression" },
@@ -537,8 +532,8 @@ static const struct cmd_bind def_cmd_binds[] = {
{ { KEY_STOP, 0 }, "quit" },
{ { KEY_FORWARD, 0 }, "seek 60" },
{ { KEY_REWIND, 0 }, "seek -60" },
- { { KEY_NEXT, 0 }, "pt_step 1" },
- { { KEY_PREV, 0 }, "pt_step -1" },
+ { { KEY_NEXT, 0 }, "playlist_next" },
+ { { KEY_PREV, 0 }, "playlist_prev" },
{ { KEY_VOLUME_UP, 0 }, "volume 1" },
{ { KEY_VOLUME_DOWN, 0 }, "volume -1" },
{ { KEY_MUTE, 0 }, "mute" },
@@ -709,13 +704,12 @@ static char *get_key_combo_name(int *keys, int max)
return ret;
}
-static bool is_abort_cmd(int cmd_id)
+bool mp_input_is_abort_cmd(int cmd_id)
{
switch (cmd_id) {
case MP_CMD_QUIT:
- case MP_CMD_PLAY_TREE_STEP:
- case MP_CMD_PLAY_TREE_UP_STEP:
- case MP_CMD_PLAY_ALT_SRC_STEP:
+ case MP_CMD_PLAYLIST_NEXT:
+ case MP_CMD_PLAYLIS