Пример #1
0
/* Initialize the script playlist handler */
int
ices_playlist_script_initialize (playlist_module_t* pm)
{
  ices_log_debug ("Initializing script playlist handler...");

  if (!pm->module) {
    ices_log_error ("No playlist script defined");
    return 0;
  }
  
  cmd = pm->module;
  /* make path relative to module dir */
  if (cmd[0] != '/' && 
      !(cmd[0] == '.' && (cmd[1] == '/' || (cmd[1] == '.' && cmd[2] == '/'))))
  {
      cmd = malloc (strlen(pm->module) + strlen(ICES_MODULEDIR) + 2);
      if (cmd)
        sprintf (cmd, "%s/%s", ICES_MODULEDIR, pm->module);
  } else
    cmd = strdup(pm->module);
    
  if (!cmd) {
    ices_log_error("Could not allocate memory for playlist path");
    return 0;
  }

  pm->get_next = playlist_script_get_next;
  pm->get_metadata = playlist_script_get_metadata;
  pm->get_lineno = NULL;
  pm->shutdown = playlist_script_shutdown;

  return 1;
}
Пример #2
0
int ices_playlist_perl_initialize(playlist_module_t* pm) {
	char *str;
	int ret = -1;

	pm->get_next = playlist_perl_get_next;
	pm->get_metadata = playlist_perl_get_metadata;
	pm->get_lineno = playlist_perl_get_lineno;
	pm->shutdown = playlist_perl_shutdown;
	pm->reload = playlist_perl_reload;

	if (pl_perl_init_perl() < 0)
		return -1;

	if (!pl_init_hook)
		return 1;

	if ((str = pl_perl_eval(pl_init_hook))) {
		ret = atoi(str);
		ices_util_free(str);
	}

	if (ret <= 0)
		ices_log_error("Execution of 'ices_init' failed");

	return ret;
}
Пример #3
0
/* Call python function to initialize the python script */
int
ices_playlist_python_initialize (playlist_module_t* pm)
{
    PyObject* res;
    int rc = 1;

    pm->get_next = playlist_python_get_next;
    pm->get_metadata = playlist_python_get_metadata;
    pm->get_lineno = playlist_python_get_lineno;
    pm->reload = playlist_python_reload;
    pm->shutdown = playlist_python_shutdown;

    if (python_init () < 0)
        return -1;

    if (pl_init_hook) {
        if ((res = python_eval (pl_init_hook)) && PyInt_Check (res))
            rc = PyInt_AsLong (res);
        else
            ices_log_error ("ices_init failed");

        Py_XDECREF (res);
    }

    return rc;
}
Пример #4
0
/* Call python function to get next file to play */
char *
interpreter_playlist_python_get_next (void)
{
	PyObject *res = (PyObject *)interpreter_python_eval_function ("ices_python_get_next");

	if (res && PyString_Check (res))
		return ices_util_strdup (PyString_AsString (res));
	ices_log_error ("Execution of 'ices_python_get_next()' in ices.py failed");
	return NULL;
}
Пример #5
0
/* Call python function to shutdown the script */
int
interpreter_playlist_python_shutdown (ices_config_t *ices_config)
{
	PyObject *res = (PyObject *)interpreter_python_eval_function ("ices_python_shutdown");

	if (res && PyInt_Check (res))
		return PyInt_AsLong (res);

	ices_log_error ("Execution of 'ices_python_shutdown()' in ices.py failed");
	return 0;
}
Пример #6
0
/* Call the python function to get the current line number */
int
interpreter_playlist_python_get_current_lineno (void)
{
	PyObject *res = (PyObject *)interpreter_python_eval_function ("ices_python_get_current_lineno");

	if (res && PyInt_Check (res))
		return PyInt_AsLong (res);

	ices_log_error ("Execution of 'ices_python_get_current_lineno()' in ices.py failed");
	return 0;
}
Пример #7
0
/* Call python function to shutdown the script */
static void playlist_python_shutdown(void) {
	PyObject* res;

	if (pl_shutdown_hook) {
		if (!((res = python_eval(pl_shutdown_hook)) && PyInt_Check(res)))
			ices_log_error("ices_shutdown failed");

		Py_XDECREF(res);
	}

	python_shutdown();
}
Пример #8
0
/* Call python function to get next file to play */
static char *playlist_python_get_next(void) {
	PyObject* res;
	char* rc = NULL;

	if ((res = python_eval(pl_get_next_hook)) && PyString_Check(res))
		rc = ices_util_strdup(PyString_AsString(res));
	else
		ices_log_error("ices_get_next failed");

	Py_XDECREF(res);

	return rc;
}
Пример #9
0
static void metadata_update(int delay) {
	ices_stream_t* stream;
	shout_metadata_t* metadata;
	char song[1024];
	char* playlist_metadata;
	char* value;
	int rc;

	if (delay)
		usleep(delay);

	if (!(playlist_metadata = ices_playlist_get_metadata())) {
		if (Title) {
			if (Artist)
				snprintf(song, sizeof(song), "%s - %s", Artist, Title);
			else
				snprintf(song, sizeof(song), "%s", Title);
		} else
			snprintf(song, sizeof(song), "%s", Filename);

		value = song;
	} else
		value = playlist_metadata;

	if (!(metadata = shout_metadata_new())) {
		ices_log_error("Error allocating metadata structure");
		ices_util_free(playlist_metadata);
		return;
	}

	if (shout_metadata_add(metadata, "song", value) != SHOUTERR_SUCCESS) {
		ices_log_error_output("Error adding info to metadata structure");
		ices_util_free(playlist_metadata);
		shout_metadata_free(metadata);
		return;
	}

	for (stream = ices_config.streams; stream; stream = stream->next) {
		rc = shout_set_metadata(stream->conn, metadata);

		if (rc != SHOUTERR_SUCCESS)
			ices_log_error_output("Updating metadata on %s failed.", stream->mount);
		else
			ices_log_debug("Updated metadata on %s to: %s", stream->mount, value);
	}

	ices_util_free(playlist_metadata);
	shout_metadata_free(metadata);
}
Пример #10
0
/* Attempt to reload the playlist module */
static int playlist_python_reload(void) {
	PyObject* new_module;

	if (!(new_module = PyImport_ReloadModule(python_module))) {
		ices_log_error("Playlist module reload failed");
		PyErr_Print();

		return -1;
	}

	python_module = new_module;
	ices_log_debug("Playlist module reloaded");

	return 0;
}
Пример #11
0
/* Call the python function to get the current line number */
static int playlist_python_get_lineno(void) {
	PyObject* res;
	int rc = 0;

	if (pl_get_lineno_hook) {
		if ((res = python_eval(pl_get_lineno_hook)) && PyInt_Check(res))
			rc = PyInt_AsLong(res);
		else
			ices_log_error("ices_get_lineno failed");

		Py_XDECREF(res);
	}

	return rc;
}
Пример #12
0
/* private functions */
static int cf_init(void) {
  if (!(FL = malloc(FadeSamples * 2)))
    goto err;
  if (!(FR = malloc(FadeSamples * 2)))
    goto err;
  if (!(Swap = malloc(FadeSamples * 2)))
    goto err;

  ices_log_debug("Crossfading %d seconds between tracks", Fadelen);
  return 0;

  err:
  ices_log_error("Crossfader could not allocate memory");
  cf_shutdown();
  return -1;
}
Пример #13
0
/* Force the python interpreter to look in our module path
 * and in the current directory for modules */
static int python_setup_path(void) {
	char *oldpath = getenv("PYTHONPATH");

	if (oldpath && (python_path = (char*) malloc(strlen(oldpath) + strlen(ICES_MODULEDIR) + 15)))
		sprintf(python_path, "PYTHONPATH=%s:%s:.", oldpath, ICES_MODULEDIR);
	else if ((python_path = (char*) malloc(strlen(ICES_MODULEDIR) + 14)))
		sprintf(python_path, "PYTHONPATH=%s:.", ICES_MODULEDIR);
	else {
		ices_log_error("Could not allocate memory for python environment");
		return -1;
	}

	putenv(python_path);

	return 0;
}
Пример #14
0
static int
ices_vorbis_readpcm (input_stream_t* self, size_t olen, int16_t* left,
		     int16_t* right)
{
  ices_vorbis_in_t* vorbis_data = (ices_vorbis_in_t*) self->data;
  int pos;
  int len;
  int i;

  /* refill buffer if necessary */
  if (! vorbis_data->samples) {
    vorbis_data->offset = 0;
    do {
      if ((len = ov_read (vorbis_data->vf, (char*) vorbis_data->buf,
			  sizeof (vorbis_data->buf), ICES_OV_BE, SAMPLESIZE, 1, &pos)) <= 0) {
	if (len == OV_HOLE) {
	  ices_log_error ("Skipping bad vorbis data");
	} else
	  return len;
      }
    } while (len <= 0);

    vorbis_data->samples = len / SAMPLESIZE;
    if (vorbis_data->info->channels > 1)
      vorbis_data->samples /= vorbis_data->info->channels;
    self->bytes_read = ov_raw_tell (vorbis_data->vf);
  }

  len = 0;
  while (vorbis_data->samples && olen) {
    if (vorbis_data->info->channels == 1) {
      *left = *right = vorbis_data->buf[vorbis_data->offset++];
      left++;
      right++;
    } else {
      *left++ = vorbis_data->buf[vorbis_data->offset++];
      *right++ = vorbis_data->buf[vorbis_data->offset++];
    }
    for (i = 0; i < vorbis_data->info->channels - 2; i++)
      vorbis_data->offset++;
    vorbis_data->samples--;
    olen -= SAMPLESIZE;
    len++;
  }

  return len;
}
Пример #15
0
/* Return the current cue filename, and create it if
 * necessary */
const char *
ices_cue_get_filename (void)
{
  static char buf[1024];

  if (ices_cue_filename)
    return ices_cue_filename;

  if (! ices_config.base_directory) {
    ices_log_error ("Base directory is invalid");
    return NULL;
  }

  snprintf (buf, sizeof (buf), "%s/ices.cue", ices_config.base_directory);

  return buf;
}
Пример #16
0
static int pl_perl_init_perl(void) {
	static char *my_argv[4] = { "", "-I" ICES_MODULEDIR, "-e", NULL };
	static char module_space[255];

	if ((my_perl = perl_alloc()) == NULL) {
		ices_log_debug("perl_alloc() error: (no memory!)");
		return -1;
	}

	snprintf(module_space, sizeof(module_space), "use %s",
		 ices_config.pm.module);
	my_argv[3] = module_space;

	perl_construct(my_perl);

	ices_log_debug("Importing perl module: %s", my_argv[3] + 4);

	if (perl_parse(my_perl, xs_init, 4, my_argv, NULL)) {
		ices_log_debug("perl_parse() error: parse problem");
		return -1;
	}

	if (!(pl_init_hook = pl_find_func("ices_init")))
		pl_init_hook = pl_find_func("ices_perl_initialize");
	if (!(pl_shutdown_hook = pl_find_func("ices_shutdown")))
		pl_shutdown_hook = pl_find_func("ices_perl_shutdown");
	if (!(pl_get_next_hook = pl_find_func("ices_get_next")))
		pl_get_next_hook = pl_find_func("ices_perl_get_next");
	if (!(pl_get_metadata_hook = pl_find_func("ices_get_metadata")))
		pl_get_metadata_hook = pl_find_func("ices_perl_get_metadata");
	if (!(pl_get_lineno_hook = pl_find_func("ices_get_lineno")))
		pl_get_lineno_hook = pl_find_func("ices_perl_get_current_lineno");

	if (!pl_get_next_hook) {
		ices_log_error("The playlist module must define at least the ices_get_next method");
		return -1;
	}

	return 0;
}
Пример #17
0
/* Function to initialize the python interpreter */
static int
python_init (void)
{
    /* For some reason, python refuses to look in the
     * current directory for modules */
    if (python_setup_path () < 0)
        return -1;

    Py_Initialize ();

    ices_log_debug ("Importing %s.py module...", ices_config.pm.module);

    /* Call the python api code to import the module */
    if (!(python_module = PyImport_ImportModule (ices_config.pm.module))) {
        ices_log ("Error: Could not import module %s", ices_config.pm.module);
        PyErr_Print();
        return -1;
    }

    /* Find defined methods */
    pl_init_hook = python_find_attr (python_module, "ices_init",
                                     "ices_python_initialize");
    pl_shutdown_hook = python_find_attr (python_module, "ices_shutdown",
                                         "ices_python_shutdown");
    pl_get_next_hook = python_find_attr (python_module, "ices_get_next",
                                         "ices_python_get_next");
    pl_get_metadata_hook = python_find_attr (python_module, "ices_get_metadata",
                           "ices_python_get_metadata");
    pl_get_lineno_hook = python_find_attr (python_module, "ices_get_lineno",
                                           "ices_python_get_current_lineno");

    if (! pl_get_next_hook) {
        ices_log_error ("The playlist module must define at least the ices_get_next method");
        return -1;
    }

    return 0;
}
Пример #18
0
static void
metadata_update (input_stream_t* source, int delay)
{
  ices_stream_t* stream;
  char song[1024];
  char* playlist_metadata;
  char* metadata;
  int rc;

  if (delay)
    usleep (delay);

  if (! (playlist_metadata = ices_playlist_get_metadata ())) {
    if (Title) {
      if (Artist)
	snprintf (song, sizeof (song), "%s - %s", Artist, Title);
      else
	snprintf (song, sizeof (song), "%s", Title);
    } else
      metadata_clean_filename (source->path, song, sizeof (song));
    
    metadata = song;
  } else
    metadata = playlist_metadata;

  for (stream = ices_config.streams; stream; stream = stream->next) {
    rc = shout_update_metadata (&stream->conn, metadata);
	
    if (rc != 1)
      ices_log_error ("Updating metadata on %s failed.", stream->mount);
    else
      ices_log_debug ("Updated metadata on %s to: %s", stream->mount, metadata);
  }

  ices_util_free (playlist_metadata);
}
Пример #19
0
static char *
playlist_script_get_next (void)
{
  char *filename = NULL, *metadata = NULL;
  FILE *pipe;
  int i = 0;

  filename = malloc(STR_BUFFER);
  metadata = malloc(STR_BUFFER);
	
  pipe = popen(cmd, "r");

  if (!pipe) {
	  ices_log_error ("Couldn't open pipe to program \"%s\"", cmd);
	  return NULL;
  }

  if (fgets(filename, STR_BUFFER, pipe) == NULL) {
	  ices_log_error ("Couldn't read filename from pipe to program \"%s\"", cmd);
	  free(filename); filename = NULL;
	  free(metadata); metadata = NULL;
	  pclose(pipe);
	  return NULL;
  }

  if (fgets(metadata, STR_BUFFER, pipe) == NULL) {
	  /* This is non-fatal. */
	  ices_log_debug ("No metadata received from pipe to program \"%s\"", cmd);
	  free(metadata); metadata = NULL;
  }
	  
  pclose(pipe);

  if (filename[0] == '\n' || (filename[0] == '\r' && filename[1] == '\n')) {
		ices_log_error ("Got newlines instead of filename from program \"%s\"", cmd);
		free(filename); filename = NULL;
		free(metadata); metadata = NULL;
		pclose(pipe);
		return NULL;
  }

  /* Remove linefeeds etc. */
  i = 0;
  while (filename[i]) {
	  if (filename[i] == '\r' || filename[i] == '\n') {
		  filename[i] = '\0';
		  break;
	  }
	  i++;
  }
  i = 0;
  while (metadata && metadata[i]) {
	  if (metadata[i] == '\r' || metadata[i] == '\n') {
		  metadata[i] = '\0';
		  break;
	  }
	  i++;
  }

  if (playlist_metadata)
	  free(playlist_metadata);
  if (metadata) 
	  playlist_metadata = metadata;
  else
	  playlist_metadata = NULL;
  
  ices_log_debug ("Script playlist handler serving: %s [%s]", ices_util_nullcheck (filename), ices_util_nullcheck(playlist_metadata));

  return filename;
}
Пример #20
0
/* try to open a vorbis file for decoding. Returns:
 *   0: success
 *   1: not a vorbis file
 *  -1: error opening
 */
int
ices_vorbis_open (input_stream_t* self, char* buf, size_t len)
{
  ices_vorbis_in_t* vorbis_data;
  OggVorbis_File* vf;
  FILE* fin;
  char errbuf[128];
  int rc;

  if (! (fin = fdopen (self->fd, "rb"))) {
    ices_util_strerror (errno, errbuf, sizeof (errbuf));
    ices_log_error ("Error opening %s: %s", self->path, errbuf);

    return -1;
  }

  if (! (vf = (OggVorbis_File*) malloc (sizeof (OggVorbis_File)))) {
    ices_log_error ("Malloc failed in ices_vorbis_open");
    return -1;
  }

  if ((rc = ov_open (fin, vf, buf, len)) != 0) {
    free (vf);
    fclose (fin);

    if (rc == OV_ENOTVORBIS)
      return 1;

    if (rc == OV_EREAD)
      ices_log_error ("Read error opening vorbis file");
    else if (rc == OV_EVERSION)
      ices_log_error ("Vorbis version mismatch");
    else if (rc == OV_EBADHEADER)
      ices_log_error ("Invalid vorbis header");
    else
      ices_log_error ("Error in ov_open: %d", rc);

    return -1;
  }

  if (!(vorbis_data = (ices_vorbis_in_t*)malloc (sizeof (ices_vorbis_in_t)))) {
    ices_log_error ("Malloc failed in ices_vorbis_open");
    ov_clear (vf);
    free (vf);
    return -1;
  }

  if (!(vorbis_data->info = ov_info(vf, -1))) {
    ices_log_error ("Vorbis: error reading vorbis info");
    ices_vorbis_close (self);

    return -1;
  }
  
  if (vorbis_data->info->channels < 1) {
    ices_log_error ("Vorbis: Cannot decode, %d channels of audio data!",
                    vorbis_data->info->channels);
    ices_vorbis_close (self);

    return -1;
  }

  self->bitrate = vorbis_data->info->bitrate_nominal / 1000;
  if (! self->bitrate)
    self->bitrate = ov_bitrate (vf, -1) / 1000;
  self->samplerate = (unsigned int) vorbis_data->info->rate;

  ices_log_debug("Ogg vorbis file found, version %d, %d kbps, %d channels, %ld Hz",
                 vorbis_data->info->version, self->bitrate, vorbis_data->info->channels,
		 self->samplerate);

  vorbis_data->vf = vf;
  vorbis_data->samples = 0;

  self->type = ICES_INPUT_VORBIS;
  self->data = vorbis_data;

  self->read = NULL;
  self->readpcm = ices_vorbis_readpcm;
  self->close = ices_vorbis_close;

  in_vorbis_set_metadata (vorbis_data);
  
  return 0;
}