view parser-mpcmd.c @ 12082:f705b0777572

removing subpackets (everyone hates them ...) removing shuffle_type (meaningless without subpackets) making timestamp_lsb a simple unsigned value (someone proposed that a long time ago, dunno dont remember who, IIRC it was rejected as it more often required the timestamp_msb to be coded but by defining lsb relative to the last lsb we need very few msbs in the error free case and for damaged files its also pretty difficult to trash the timestamp, for example for a fixed fps stream with 7bit lsb_timestamps we need to loose >64 frames in a row to end up with a wrong timestamp) cleanup (filesize and such where only partially removed) frame_code byte, with the meaning of each value stored in the main header the frame_code contains the keyframe_flag, packet_type and can contain the timestamp_delta, stream_id and the data_size or part if it
author michael
date Tue, 30 Mar 2004 01:05:51 +0000
parents 522afd56703c
children 14bdbd687113
line wrap: on
line source

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#ifdef MP_DEBUG
#include <assert.h>
#endif

#include "mp_msg.h"
#include "m_option.h"
#include "m_config.h"
#include "playtree.h"

static int recursion_depth = 0;
static int mode = 0;

#define GLOBAL 0
#define LOCAL 1
#define DROP_LOCAL 2

#define UNSET_GLOBAL (mode = LOCAL)
// Use this 1 if you want to have only global option (no per file option)
// #define UNSET_GLOBAL (mode = GLOBAL)


static int is_entry_option(char *opt, char *param, play_tree_t** ret) {
  play_tree_t* entry = NULL;

  *ret = NULL;

  if(strcasecmp(opt,"playlist") == 0) { // We handle playlist here
    if(!param)
      return M_OPT_MISSING_PARAM;
    entry = parse_playlist_file(param);
    if(!entry)
      return 1;
  }

  if(entry) {
    *ret = entry;
    return 1;
  } else
    return 0;
}

static inline void add_entry(play_tree_t **last_parentp,
	play_tree_t **last_entryp, play_tree_t *entry) {
    if(*last_entryp == NULL)
      play_tree_set_child(*last_parentp,entry);		      
    else 
      play_tree_append_entry(*last_entryp,entry);
    *last_entryp = entry;
}

play_tree_t*
m_config_parse_mp_command_line(m_config_t *config, int argc, char **argv)
{
  int i;
  int tmp = 0;
  char *opt;
  int no_more_opts = 0;
  play_tree_t *last_parent, *last_entry = NULL, *root;

#ifdef MP_DEBUG
  assert(config != NULL);
  assert(argv != NULL);
  assert(argc >= 1);
#endif

  config->mode = M_COMMAND_LINE;
  mode = GLOBAL;
  last_parent = root = play_tree_new();
  /* in order to work recursion detection properly in parse_config_file */
  ++recursion_depth;

  for (i = 1; i < argc; i++) {
    //next:
    opt = argv[i];
    /* check for -- (no more options id.) except --help! */
    if ((*opt == '-') && (*(opt+1) == '-') && (*(opt+2) != 'h'))
      {
	no_more_opts = 1;
	if (i+1 >= argc)
	  {
	    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "You added '--' but no filenames presented!\n");
	    goto err_out;
	  }
	continue;
      }
    if((opt[0] == '{') && (opt[1] == '\0'))
      {
	play_tree_t* entry = play_tree_new();
	UNSET_GLOBAL;
	if(last_parent->flags & PLAY_TREE_RND)
	  entry->flags |= PLAY_TREE_RND;
	if(last_entry == NULL) {
	  play_tree_set_child(last_parent,entry);
	} else {
	  play_tree_append_entry(last_entry,entry);
	  last_entry = NULL;
	}
	last_parent = entry;
	continue;
      }

    if((opt[0] == '}') && (opt[1] == '\0'))
      {
	if( ! last_parent || ! last_parent->parent) {
	  mp_msg(MSGT_CFGPARSER, MSGL_ERR, "too much }-\n");
	  goto err_out;
	}
	last_entry = last_parent;
	last_parent = last_entry->parent;
	continue;
      }
			
    if ((no_more_opts == 0) && (*opt == '-') && (*(opt+1) != 0)) /* option */
      {
	/* remove trailing '-' */
	opt++;

	mp_msg(MSGT_CFGPARSER, MSGL_DBG3, "this_opt = option: %s\n", opt);
	// We handle here some specific option
	if(strcasecmp(opt,"list-options") == 0) {
	  m_config_print_option_list(config);
	  exit(1);
	  // Loop option when it apply to a group
	} else if(strcasecmp(opt,"loop") == 0 &&
		  (! last_entry || last_entry->child) ) {
	  int l;
	  char* end;
	  l = (i+1<argc) ? strtol(argv[i+1],&end,0) : 0;
	  if(*end != '\0') {
	    mp_msg(MSGT_CFGPARSER, MSGL_ERR, "The loop option must be an integer: %s\n",argv[i+1]);
	    tmp = ERR_OUT_OF_RANGE;
	  } else {
	    play_tree_t* pt = last_entry ? last_entry : last_parent;
	    l = l <= 0 ? -1 : l;
	    pt->loop = l;
	    tmp = 1;
	  }
	} else if(strcasecmp(opt,"shuffle") == 0) {
	  if(last_entry && last_entry->child)
	    last_entry->flags |= PLAY_TREE_RND;
	  else
	    last_parent->flags |= PLAY_TREE_RND;
	} else if(strcasecmp(opt,"noshuffle") == 0) {
	  if(last_entry && last_entry->child)
	    last_entry->flags &= ~PLAY_TREE_RND;
	  else
	    last_parent->flags &= ~PLAY_TREE_RND;
	} else {
	  m_option_t* mp_opt = NULL;
	  play_tree_t* entry = NULL;

	  tmp = is_entry_option(opt,(i+1<argc) ? argv[i + 1] : NULL,&entry);
	  if(tmp > 0)  { // It's an entry
	    if(entry) {
	      add_entry(&last_parent,&last_entry,entry);
	      if((last_parent->flags & PLAY_TREE_RND) && entry->child)
		entry->flags |= PLAY_TREE_RND;
	      UNSET_GLOBAL;
	    } else if(mode == LOCAL) // Entry is empty we have to drop his params
	      mode = DROP_LOCAL;
	  } else if(tmp == 0) { // 'normal' options
	    mp_opt = m_config_get_option(config,opt);
	    if (mp_opt != NULL) { // Option exist
	      if(mode == GLOBAL || (mp_opt->flags & M_OPT_GLOBAL))
                tmp = (i+1<argc) ? m_config_set_option(config, opt, argv[i + 1])
				 : m_config_set_option(config, opt, NULL);
	      else {
		tmp = m_config_check_option(config, opt, (i+1<argc) ? argv[i + 1] : NULL);
		if(tmp >= 0 && mode != DROP_LOCAL) {
		  play_tree_t* pt = last_entry ? last_entry : last_parent;
		  play_tree_set_param(pt,opt, argv[i + 1]);
		}
	      }
	    } else {
	      tmp = M_OPT_UNKNOWN;
	      mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknown option on the command line: %s\n",opt);
	    }
	  }
	}

	if (tmp < 0) {
	  if (tmp == M_OPT_EXIT)
	    exit(0);
	  goto err_out;
	}
	i += tmp;
      }
    else /* filename */
      {
	play_tree_t* entry = play_tree_new();
	mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Adding file %s\n",argv[i]);
	play_tree_add_file(entry,argv[i]);
	// Lock stdin if it will be used as input
	if(strcasecmp(argv[i],"-") == 0)
	  m_config_set_option(config,"use-stdin",NULL);
	add_entry(&last_parent,&last_entry,entry);
	UNSET_GLOBAL; // We start entry specific options

      }
  }

  --recursion_depth;
  if(last_parent != root)
    mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Missing }- ?\n");
  return root;

 err_out:
  --recursion_depth;
  play_tree_free(root,1);
  return NULL;
}