Mercurial > mplayer.hg
view playtree.c @ 4218:3931c41f740a
Added new syncengine thanks to a new previously undocumented feature of the em8300, this might fix playback on both slow and fast machines (more testing needed). This also requires users to get the em8300 driver from cvs until the next version is released (will probably happen this weekend)
Added lots of comments, should be pretty easy to understand most of the internals now
Added lots of brackets to if's for's while's etc, this is not a cosmetical thing but rather due to the fact I got some very odd bugs with else's since I didn't properly use brackets (and it's the K&R standard to have brackets everywhere)
Fixed some bugs that would occur when disabling libmp1e
Switched to default to the new naming scheme of device nodes, the driver will slowly switch over to this state, if it can't find devices under the new name it will try the old naming scheme
I stopped opening devices in non-blocking mode, it would break the new syncengine which tries to burst data to the device (alot of times meaning it will fill the fifo pretty fast which would previously result in jerkyness on fast machines)
The device now sets the initial state of the pts and speed (probably not needed, but assumption is the mother of all fuckups =)
Keep the control interface open during the entire duration of the libvo device, we might need this to flush video buffers on seeking (currently not implemented, therefore seeking is broken)
This is beta stuff to the driver, I will get some users to test it for me and do my best to fix seeking as soon as possible...
author | mswitch |
---|---|
date | Thu, 17 Jan 2002 10:33:47 +0000 |
parents | 22fadd4022b5 |
children | fe2c20d52a25 |
line wrap: on
line source
#include "config.h" #include <stdlib.h> #include <string.h> #include <stdio.h> #include <unistd.h> #ifdef MP_DEBUG #include <assert.h> #endif #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 = (play_tree_t*)calloc(1,sizeof(play_tree_t)); if(r == NULL) mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",sizeof(play_tree_t)); return r; } void play_tree_free(play_tree_t* pt, int childs) { play_tree_t* iter; #ifdef MP_DEBUG assert(pt != NULL); #endif if(childs) { for(iter = pt->child; iter != NULL; iter = iter->next) play_tree_free(iter,1); 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 childs) { play_tree_t* iter; #ifdef MP_DEBUG assert(pt != NULL); #endif for(iter = pt ; iter->prev != NULL ; iter = iter->prev) /* NOTHING */; for( ; iter != NULL ; iter = iter->next) play_tree_free(iter,childs); } 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_childs) { #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; } // Begining 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_childs); } 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->files == NULL); #endif 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; #ifdef MP_DEBUG assert(pt != NULL); assert(pt->child == NULL); assert(file != NULL); #endif 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)*sizeof(char*)); return; } pt->files[n] = strdup(file); pt->files[n+1] = NULL; } 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->files != NULL); #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)*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; return; } pt->params = (play_tree_param_t*)realloc(pt->params,(n+2)*sizeof(play_tree_param_t)); 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*sizeof(play_tree_param_t)); return -1; } } else { free(pt->params); pt->params = NULL; } return 1; } static int 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; if(pt->params == NULL) return 0; m_config_push(iter->config); for(n = 0; pt->params[n].name != NULL ; n++) { if(m_config_set_option(iter->config,pt->params[n].name,pt->params[n].value) < 0) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Error while setting option '%s' with value '%s'\n", pt->params[n].name,pt->params[n].value); } } //printf("Param pushed\n"); return 1; } static void play_tree_iter_pop_params(play_tree_iter_t* iter) { #ifdef MP_DEBUG assert(iter != NULL); assert(iter->config != NULL); #endif if(iter->tree->params == NULL) return; //printf("Poping params\n"); m_config_pop(iter->config); } 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 = (play_tree_iter_t*)calloc(1,sizeof(play_tree_iter_t)); if(! iter) 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); } int play_tree_iter_step(play_tree_iter_t* iter, int d,int with_nodes) { play_tree_t* pt; #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) { play_tree_iter_pop_params(iter); iter->entry_pushed = 0; } iter->file = 0; if( d > 0 ) pt = iter->tree->next; else if(d < 0) pt = iter->tree->prev; else pt = iter->tree; if(pt == NULL) { // No next // Must we loop? 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 childs ? 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 enty ? if(! play_tree_is_valid(pt)) { if(d == 0) { // Can this happen ? 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) iter->entry_pushed = play_tree_iter_push_params(iter); 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->files != NULL) 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 = 0; 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]; iter->status_stack = (int*)realloc(iter->status_stack,iter->stack_size*sizeof(int)); 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*sizeof(char*)); return PLAY_TREE_ITER_ERROR; } iter->tree = iter->tree->parent; // Pop subtree params if(iter->config) play_tree_iter_pop_params(iter); 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 = 0; // 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*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; if(d > 0) { if(iter->tree->files[iter->file] == NULL) return NULL; iter->file++; } else if(d < 0) { if(iter->file == 0) return NULL; iter->file--; } return iter->tree->files[iter->file-1]; } 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 = (play_tree_iter_t*)malloc(sizeof(play_tree_iter_t)); if(iter == NULL) { mp_msg(MSGT_PLAYTREE,MSGL_ERR,"Can't allocate %d bytes of memory\n",sizeof(play_tree_iter_t)); return NULL; } ; memcpy(iter,old,sizeof(play_tree_iter_t)); if(old->status_stack) { iter->status_stack = (int*)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 * sizeof(int)); free(iter); return NULL; } memcpy(iter->status_stack,old->status_stack,iter->stack_size*sizeof(int)); } iter->config = NULL; return iter; }