1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-27 17:42:17 +00:00
mpv/playtree.c
Anton Khirnov 87366694d8 Remove the internal GUI
The GUI is badly designed and too closely coupled to the internal
details of other code. The GUI code is in bad shape and unmaintained
for years. There is no indication that anyone would maintain it in the
future either. Even if someone did volunteer to implement a better
integrated GUI having the current code in the tree probably wouldn't
help much. So get rid of it.
2009-07-07 21:49:42 +03:00

954 lines
20 KiB
C

/// \file
/// \ingroup Playtree
#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#ifdef MP_DEBUG
#include <assert.h>
#endif
#include "m_config.h"
#include "playtree.h"
#include "mp_msg.h"
static int
play_tree_is_valid(play_tree_t* pt);
play_tree_t*
play_tree_new(void) {
play_tree_t* r = calloc(1,sizeof(play_tree_t));
if(r == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(int)sizeof(play_tree_t));
return NULL;
}
r->entry_type = PLAY_TREE_ENTRY_NODE;
return r;
}
void
play_tree_free(play_tree_t* pt, int children) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
if(children) {
for(iter = pt->child; iter != NULL; ) {
play_tree_t* nxt=iter->next;
play_tree_free(iter,1);
iter = nxt;
}
pt->child = NULL;
}
play_tree_remove(pt,0,0);
for(iter = pt->child ; iter != NULL ; iter = iter->next)
iter->parent = NULL;
//if(pt->params) free(pt->params);
if(pt->files) {
int i;
for(i = 0 ; pt->files[i] != NULL ; i++)
free(pt->files[i]);
free(pt->files);
}
free(pt);
}
void
play_tree_free_list(play_tree_t* pt, int children) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
for(iter = pt ; iter->prev != NULL ; iter = iter->prev)
/* NOTHING */;
while(iter) {
play_tree_t* nxt = iter->next;
play_tree_free(iter, children);
iter = nxt;
}
}
void
play_tree_append_entry(play_tree_t* pt, play_tree_t* entry) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
if(pt == entry)
return;
for(iter = pt ; iter->next != NULL ; iter = iter->next)
/* NOTHING */;
entry->parent = iter->parent;
entry->prev = iter;
entry->next = NULL;
iter->next = entry;
}
void
play_tree_prepend_entry(play_tree_t* pt, play_tree_t* entry) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
for(iter = pt ; iter->prev != NULL; iter = iter->prev)
/* NOTHING */;
entry->prev = NULL;
entry->next = iter;
entry->parent = iter->parent;
iter->prev = entry;
if(entry->parent) {
#ifdef MP_DEBUG
assert(entry->parent->child == iter);
#endif
entry->parent->child = entry;
}
}
void
play_tree_insert_entry(play_tree_t* pt, play_tree_t* entry) {
#ifdef MP_DEBUG
assert(pt != NULL);
assert(entry != NULL);
#endif
entry->parent = pt->parent;
entry->prev = pt;
if(pt->next) {
#ifdef MP_DEBUG
assert(pt->next->prev == pt);
#endif
entry->next = pt->next;
entry->next->prev = entry;
} else
entry->next = NULL;
pt->next = entry;
}
void
play_tree_remove(play_tree_t* pt, int free_it, int with_children) {
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
// Middle of list
if(pt->prev && pt->next) {
#ifdef MP_DEBUG
assert(pt->prev->next == pt);
assert(pt->next->prev == pt);
#endif
pt->prev->next = pt->next;
pt->next->prev = pt->prev;
} // End of list
else if(pt->prev) {
#ifdef MP_DEBUG
assert(pt->prev->next == pt);
#endif
pt->prev->next = NULL;
} // Beginning of list
else if(pt->next) {
#ifdef MP_DEBUG
assert(pt->next->prev == pt);
#endif
pt->next->prev = NULL;
if(pt->parent) {
#ifdef MP_DEBUG
assert(pt->parent->child == pt);
#endif
pt->parent->child = pt->next;
}
} // The only one
else if(pt->parent) {
#ifdef MP_DEBUG
assert(pt->parent->child == pt);
#endif
pt->parent->child = NULL;
}
pt->prev = pt->next = pt->parent = NULL;
if(free_it)
play_tree_free(pt,with_children);
}
void
play_tree_set_child(play_tree_t* pt, play_tree_t* child) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(pt->entry_type == PLAY_TREE_ENTRY_NODE);
#endif
//DEBUG_FF: Where are the children freed?
// Attention in using this function!
for(iter = pt->child ; iter != NULL ; iter = iter->next)
iter->parent = NULL;
// Go back to first one
for(iter = child ; iter->prev != NULL ; iter = iter->prev)
/* NOTHING */;
pt->child = iter;
for( ; iter != NULL ; iter= iter->next)
iter->parent = pt;
}
void
play_tree_set_parent(play_tree_t* pt, play_tree_t* parent) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
if(pt->parent)
pt->parent->child = NULL;
for(iter = pt ; iter != NULL ; iter = iter->next)
iter->parent = parent;
if(pt->prev) {
for(iter = pt->prev ; iter->prev != NULL ; iter = iter->prev)
iter->parent = parent;
iter->parent = parent;
parent->child = iter;
} else
parent->child = pt;
}
void
play_tree_add_file(play_tree_t* pt,char* file) {
int n = 0;
char* e;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(pt->child == NULL);
assert(file != NULL);
#endif
if(pt->entry_type != PLAY_TREE_ENTRY_NODE &&
pt->entry_type != PLAY_TREE_ENTRY_FILE)
return;
if(pt->files) {
for(n = 0 ; pt->files[n] != NULL ; n++)
/* NOTHING */;
}
pt->files = (char**)realloc(pt->files,(n+2)*sizeof(char*));
if(pt->files ==NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*(int)sizeof(char*));
return;
}
e = pt->files[n] = strdup(file);
pt->files[n+1] = NULL;
pt->entry_type = PLAY_TREE_ENTRY_FILE;
}
int
play_tree_remove_file(play_tree_t* pt,char* file) {
int n,f = -1;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(file != NULL);
assert(pt->entry_type != PLAY_TREE_ENTRY_NODE);
#endif
for(n=0 ; pt->files[n] != NULL ; n++) {
if(strcmp(file,pt->files[n]) == 0)
f = n;
}
if(f < 0) // Not found
return 0;
#ifdef MP_DEBUG
assert(n > f);
#endif
free(pt->files[f]);
if(n > 1) {
memmove(&pt->files[f],&pt->files[f+1],(n-f)*sizeof(char*));
pt->files = (char**)realloc(pt->files,n*sizeof(char*));
if(pt->files == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(n+2)*(int)sizeof(char*));
return -1;
}
} else {
free(pt->files);
pt->files = NULL;
}
return 1;
}
void
play_tree_set_param(play_tree_t* pt, char* name, char* val) {
int n = 0,ni = -1;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(name != NULL);
#endif
if(pt->params) {
for( ; pt->params[n].name != NULL ; n++) {
if(strcasecmp(pt->params[n].name,name) == 0)
ni = n;
}
}
if(ni > 0) {
if(pt->params[n].value != NULL) free(pt->params[n].value);
pt->params[n].value = val != NULL ? strdup(val) : NULL;
return;
}
pt->params = (play_tree_param_t*)realloc(pt->params,(n+2)*sizeof(play_tree_param_t));
if(pt->params == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't realloc params (%d bytes of memory)\n",(n+2)*(int)sizeof(play_tree_param_t));
return;
}
pt->params[n].name = strdup(name);
pt->params[n].value = val != NULL ? strdup(val) : NULL;
memset(&pt->params[n+1],0,sizeof(play_tree_param_t));
return;
}
int
play_tree_unset_param(play_tree_t* pt, char* name) {
int n,ni = -1;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(name != NULL);
assert(pt->params != NULL);
#endif
for(n = 0 ; pt->params[n].name != NULL ; n++) {
if(strcasecmp(pt->params[n].name,name) == 0)
ni = n;
}
if(ni < 0)
return 0;
if(pt->params[ni].name) free(pt->params[ni].name);
if(pt->params[ni].value) free(pt->params[ni].value);
if(n > 1) {
memmove(&pt->params[ni],&pt->params[ni+1],(n-ni)*sizeof(play_tree_param_t));
pt->params = (play_tree_param_t*)realloc(pt->params,n*sizeof(play_tree_param_t));
if(pt->params == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",n*(int)sizeof(play_tree_param_t));
return -1;
}
} else {
free(pt->params);
pt->params = NULL;
}
return 1;
}
void
play_tree_set_params_from(play_tree_t* dest,play_tree_t* src) {
int i;
#ifdef MP_DEBUG
assert(dest != NULL);
assert(src != NULL);
#endif
if(!src->params)
return;
for(i = 0; src->params[i].name != NULL ; i++)
play_tree_set_param(dest,src->params[i].name,src->params[i].value);
if(src->flags & PLAY_TREE_RND) // pass the random flag too
dest->flags |= PLAY_TREE_RND;
}
// all children if deep < 0
static void
play_tree_set_flag(play_tree_t* pt, int flags , int deep) {
play_tree_t* i;
pt->flags |= flags;
if(deep && pt->child) {
if(deep > 0) deep--;
for(i = pt->child ; i ; i = i->next)
play_tree_set_flag(i,flags,deep);
}
}
static void
play_tree_unset_flag(play_tree_t* pt, int flags , int deep) {
play_tree_t* i;
pt->flags &= ~flags;
if(deep && pt->child) {
if(deep > 0) deep--;
for(i = pt->child ; i ; i = i->next)
play_tree_unset_flag(i,flags,deep);
}
}
//////////////////////////////////// ITERATOR //////////////////////////////////////
static void
play_tree_iter_push_params(play_tree_iter_t* iter) {
int n;
play_tree_t* pt;
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->config != NULL);
assert(iter->tree != NULL);
#endif
pt = iter->tree;
// We always push a config because we can set some option
// while playing
m_config_push(iter->config);
if(pt->params == NULL)
return;
for(n = 0; pt->params[n].name != NULL ; n++) {
int e;
if((e = m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value)) < 0) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error %d while setting option '%s' with value '%s'\n",e,
pt->params[n].name,pt->params[n].value);
}
}
if(!pt->child)
iter->entry_pushed = 1;
return;
}
play_tree_iter_t*
play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
play_tree_iter_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
assert(config != NULL);
#endif
if( ! play_tree_is_valid(pt))
return NULL;
iter = calloc(1,sizeof(play_tree_iter_t));
if(! iter) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate new iterator (%d bytes of memory)\n",(int)sizeof(play_tree_iter_t));
return NULL;
}
iter->root = pt;
iter->tree = NULL;
iter->config = config;
if(pt->parent)
iter->loop = pt->parent->loop;
return iter;
}
void
play_tree_iter_free(play_tree_iter_t* iter) {
#ifdef MP_DEBUG
assert(iter != NULL);
#endif
if(iter->status_stack) {
#ifdef MP_DEBUG
assert(iter->stack_size > 0);
#endif
free(iter->status_stack);
}
free(iter);
}
static play_tree_t*
play_tree_rnd_step(play_tree_t* pt) {
int count = 0;
int r;
play_tree_t *i,*head;
// Count how many free choice we have
for(i = pt ; i->prev ; i = i->prev)
if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
head = i;
if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
for(i = pt->next ; i ; i = i->next)
if(!(i->flags & PLAY_TREE_RND_PLAYED)) count++;
if(!count) return NULL;
r = (int)((float)(count) * rand() / (RAND_MAX + 1.0));
for(i = head ; i ; i=i->next) {
if(!(i->flags & PLAY_TREE_RND_PLAYED)) r--;
if(r < 0) return i;
}
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Random stepping error\n");
return NULL;
}
int
play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) {
play_tree_t* pt;
if ( !iter ) return PLAY_TREE_ITER_ENTRY;
if ( !iter->root ) return PLAY_TREE_ITER_ENTRY;
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->root != NULL);
//printf("PT : Stepping = %d\n",d);
#endif
if(iter->tree == NULL) {
iter->tree = iter->root;
return play_tree_iter_step(iter,0,with_nodes);
}
if(iter->config && iter->entry_pushed > 0) {
iter->entry_pushed = 0;
m_config_pop(iter->config);
}
if(iter->tree->parent && (iter->tree->parent->flags & PLAY_TREE_RND))
iter->mode = PLAY_TREE_ITER_RND;
else
iter->mode = PLAY_TREE_ITER_NORMAL;
iter->file = -1;
if(iter->mode == PLAY_TREE_ITER_RND)
pt = play_tree_rnd_step(iter->tree);
else if( d > 0 ) {
int i;
pt = iter->tree;
for(i = d ; i > 0 && pt ; i--)
pt = pt->next;
d = i ? i : 1;
} else if(d < 0) {
int i;
pt = iter->tree;
for(i = d ; i < 0 && pt ; i++)
pt = pt->prev;
d = i ? i : -1;
} else
pt = iter->tree;
if(pt == NULL) { // No next
// Must we loop?
if (iter->mode == PLAY_TREE_ITER_RND) {
if (iter->root->loop == 0)
return PLAY_TREE_ITER_END;
play_tree_unset_flag(iter->root, PLAY_TREE_RND_PLAYED, -1);
if (iter->root->loop > 0) iter->root->loop--;
// try again
return play_tree_iter_step(iter, 0, with_nodes);
} else
if(iter->tree->parent && iter->tree->parent->loop != 0 && ((d > 0 && iter->loop != 0) || ( d < 0 && (iter->loop < 0 || iter->loop < iter->tree->parent->loop) ) ) ) {
if(d > 0) { // Go back to the first one
for(pt = iter->tree ; pt->prev != NULL; pt = pt->prev)
/* NOTHNG */;
if(iter->loop > 0) iter->loop--;
} else if( d < 0 ) { // Or the last one
for(pt = iter->tree ; pt->next != NULL; pt = pt->next)
/* NOTHNG */;
if(iter->loop >= 0 && iter->loop < iter->tree->parent->loop) iter->loop++;
}
iter->tree = pt;
return play_tree_iter_step(iter,0,with_nodes);
}
// Go up one level
return play_tree_iter_up_step(iter,d,with_nodes);
}
// Is there any valid child?
if(pt->child && play_tree_is_valid(pt->child)) {
iter->tree = pt;
if(with_nodes) { // Stop on the node
return PLAY_TREE_ITER_NODE;
} else // Or follow it
return play_tree_iter_down_step(iter,d,with_nodes);
}
// Is it a valid entry?
if(! play_tree_is_valid(pt)) {
if(d == 0) { // Can this happen ? FF: Yes!
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"What to do now ???? Infinite loop if we continue\n");
return PLAY_TREE_ITER_ERROR;
} // Not a valid entry : go to next one
return play_tree_iter_step(iter,d,with_nodes);
}
#ifdef MP_DEBUG
assert(pt->files != NULL);
#endif
iter->tree = pt;
for(d = 0 ; iter->tree->files[d] != NULL ; d++)
/* NOTHING */;
iter->num_files = d;
if(iter->config) {
play_tree_iter_push_params(iter);
iter->entry_pushed = 1;
if(iter->mode == PLAY_TREE_ITER_RND)
pt->flags |= PLAY_TREE_RND_PLAYED;
}
return PLAY_TREE_ITER_ENTRY;
}
static int
play_tree_is_valid(play_tree_t* pt) {
play_tree_t* iter;
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
if(pt->entry_type != PLAY_TREE_ENTRY_NODE) {
#ifdef MP_DEBUG
assert(pt->child == NULL);
#endif
return 1;
}
else if (pt->child != NULL) {
for(iter = pt->child ; iter != NULL ; iter = iter->next) {
if(play_tree_is_valid(iter))
return 1;
}
}
return 0;
}
int
play_tree_iter_up_step(play_tree_iter_t* iter, int d,int with_nodes) {
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->tree != NULL);
//printf("PT : Go UP\n");
#endif
iter->file = -1;
if(iter->tree->parent == iter->root->parent)
return PLAY_TREE_ITER_END;
#ifdef MP_DEBUG
assert(iter->tree->parent != NULL);
assert(iter->stack_size > 0);
assert(iter->status_stack != NULL);
#endif
iter->stack_size--;
iter->loop = iter->status_stack[iter->stack_size];
if(iter->stack_size > 0)
iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int));
else {
free(iter->status_stack);
iter->status_stack = NULL;
}
if(iter->stack_size > 0 && iter->status_stack == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*(int)sizeof(char*));
return PLAY_TREE_ITER_ERROR;
}
iter->tree = iter->tree->parent;
// Pop subtree params
if(iter->config) {
m_config_pop(iter->config);
if(iter->mode == PLAY_TREE_ITER_RND)
iter->tree->flags |= PLAY_TREE_RND_PLAYED;
}
return play_tree_iter_step(iter,d,with_nodes);
}
int
play_tree_iter_down_step(play_tree_iter_t* iter, int d,int with_nodes) {
#ifdef MP_DEBUG
assert(iter->tree->files == NULL);
assert(iter->tree->child != NULL);
assert(iter->tree->child->parent == iter->tree);
//printf("PT : Go DOWN\n");
#endif
iter->file = -1;
// Push subtree params
if(iter->config)
play_tree_iter_push_params(iter);
iter->stack_size++;
iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int));
if(iter->status_stack == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",iter->stack_size*(int)sizeof(int));
return PLAY_TREE_ITER_ERROR;
}
iter->status_stack[iter->stack_size-1] = iter->loop;
// Set new status
iter->loop = iter->tree->loop-1;
if(d >= 0)
iter->tree = iter->tree->child;
else {
play_tree_t* pt;
for(pt = iter->tree->child ; pt->next != NULL ; pt = pt->next)
/*NOTING*/;
iter->tree = pt;
}
return play_tree_iter_step(iter,0,with_nodes);
}
char*
play_tree_iter_get_file(play_tree_iter_t* iter, int d) {
#ifdef MP_DEBUG
assert(iter != NULL);
assert(iter->tree->child == NULL);
#endif
if(iter->tree->files == NULL)
return NULL;
#ifdef MP_DEBUG
assert(iter->num_files > 0);
#endif
if(iter->file >= iter->num_files-1 || iter->file < -1)
return NULL;
if(d > 0) {
if(iter->file >= iter->num_files - 1)
iter->file = 0;
else
iter->file++;
} else if(d < 0) {
if(iter->file <= 0)
iter->file = iter->num_files - 1;
else
iter->file--;
}
return iter->tree->files[iter->file];
}
play_tree_t*
play_tree_cleanup(play_tree_t* pt) {
play_tree_t* iter, *tmp, *first;
#ifdef MP_DEBUG
assert(pt != NULL);
#endif
if( ! play_tree_is_valid(pt)) {
play_tree_remove(pt,1,1);
return NULL;
}
first = pt->child;
for(iter = pt->child ; iter != NULL ; ) {
tmp = iter;
iter = iter->next;
if(! play_tree_is_valid(tmp)) {
play_tree_remove(tmp,1,1);
if(tmp == first) first = iter;
}
}
for(iter = first ; iter != NULL ; ) {
tmp = iter;
iter = iter->next;
play_tree_cleanup(tmp);
}
return pt;
}
play_tree_iter_t*
play_tree_iter_new_copy(play_tree_iter_t* old) {
play_tree_iter_t* iter;
#ifdef MP_DEBUG
assert(old != NULL);
#endif
iter = malloc(sizeof(play_tree_iter_t));
if(iter == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",(int)sizeof(play_tree_iter_t));
return NULL;
}
;
memcpy(iter,old,sizeof(play_tree_iter_t));
if(old->status_stack) {
iter->status_stack = malloc(old->stack_size * sizeof(int));
if(iter->status_stack == NULL) {
mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",old->stack_size * (int)sizeof(int));
free(iter);
return NULL;
}
memcpy(iter->status_stack,old->status_stack,iter->stack_size*sizeof(int));
}
iter->config = NULL;
return iter;
}
// HIGH Level API, by Fabian Franz (mplayer@fabian-franz.de)
//
play_tree_iter_t* pt_iter_create(play_tree_t** ppt, m_config_t* config)
{
play_tree_iter_t* r=NULL;
#ifdef MP_DEBUG
assert(*ppt!=NULL);
#endif
*ppt=play_tree_cleanup(*ppt);
if(*ppt) {
r = play_tree_iter_new(*ppt,config);
if (r && play_tree_iter_step(r,0,0) != PLAY_TREE_ITER_ENTRY)
{
play_tree_iter_free(r);
r = NULL;
}
}
return r;
}
void pt_iter_destroy(play_tree_iter_t** iter)
{
if (iter && *iter)
{
free(*iter);
iter=NULL;
}
}
char* pt_iter_get_file(play_tree_iter_t* iter, int d)
{
int i=0;
char* r;
if (iter==NULL)
return NULL;
r = play_tree_iter_get_file(iter,d);
while (!r && d!=0)
{
if (play_tree_iter_step(iter,d,0) != PLAY_TREE_ITER_ENTRY)
break;
r=play_tree_iter_get_file(iter,d);
i++;
}
return r;
}
void pt_iter_insert_entry(play_tree_iter_t* iter, play_tree_t* entry)
{
play_tree_t *pt = iter->tree;
#ifdef MP_DEBUG
assert(pt!=NULL);
assert(entry!=NULL);
assert(entry!=pt);
#endif
play_tree_insert_entry(pt, entry);
play_tree_set_params_from(entry,pt);
}
void pt_iter_replace_entry(play_tree_iter_t* iter, play_tree_t* entry)
{
play_tree_t *pt = iter->tree;
pt_iter_insert_entry(iter, entry);
play_tree_remove(pt, 1, 1);
iter->tree=entry;
}
//Add a new file as a new entry
void pt_add_file(play_tree_t** ppt, char* filename)
{
play_tree_t *pt = *ppt, *entry = play_tree_new();
#ifdef MP_DEBUG
assert(entry!=NULL);
#endif
play_tree_add_file(entry, filename);
if (pt)
play_tree_append_entry(pt, entry);
else
{
pt=entry;
*ppt=pt;
}
play_tree_set_params_from(entry,pt);
}
void pt_iter_goto_head(play_tree_iter_t* iter)
{
iter->tree=iter->root;
play_tree_iter_step(iter, 0, 0);
}