Ejemplo n.º 1
0
static int pshoutobj_set_audio_info(ShoutObjectAttr* attr, ShoutObject* self, PyObject* v) {
  PyObject* key;
  PyObject* val;
  const char* skey;
  const char* sval;
  int i = 0;
  int rc;

  if (!PyDict_Check(v)) {
    PyErr_SetString(PyExc_TypeError, "Dictionary argument required");
    return SHOUTERR_INSANE;
  }

  while (PyDict_Next(v, &i, &key, &val)) {
    if (!PyString_Check(key)) {
      PyErr_SetString(PyExc_TypeError, "Dictionary key must be string");
      return SHOUTERR_INSANE;
    }
    if (!PyString_Check(val)) {
      PyErr_SetString(PyExc_TypeError, "Dictionary value must be string");
      return SHOUTERR_INSANE;
    }

    skey = PyString_AsString(key);
    sval = PyString_AsString(val);

    if ((rc = shout_set_audio_info(self->conn, skey, sval)) != SHOUTERR_SUCCESS)
      return rc;
  }

  return SHOUTERR_SUCCESS;
}
Ejemplo n.º 2
0
static switch_status_t shout_file_open(switch_file_handle_t *handle, const char *path)
{
	shout_context_t *context;
	char *host, *file;
	char *username, *password, *port;
	char *err = NULL;
	const char *mpg123err = NULL;
	int portno = 0;

	if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
		return SWITCH_STATUS_MEMERR;
	}

	if (!handle->samplerate) {
		handle->samplerate = 8000;
	}

	context->memory_pool = handle->memory_pool;
	context->samplerate = handle->samplerate;
	context->handle = handle;

	switch_thread_rwlock_create(&(context->rwlock), context->memory_pool);

	switch_thread_rwlock_rdlock(context->rwlock);

	switch_mutex_init(&context->audio_mutex, SWITCH_MUTEX_NESTED, context->memory_pool);

	if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
		if (switch_buffer_create_dynamic(&context->audio_buffer, TC_BUFFER_SIZE, TC_BUFFER_SIZE * 2, 0) != SWITCH_STATUS_SUCCESS) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
			goto error;
		}

		context->mh = our_mpg123_new(NULL, NULL);
		if (mpg123_format_all(context->mh) != MPG123_OK) {
			MPGERROR();
		}
		if (mpg123_param(context->mh, MPG123_FORCE_RATE, context->samplerate, 0) != MPG123_OK) {
			MPGERROR();
		}

		if (handle->handler) {
			if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_SEEKBUFFER | MPG123_MONO_MIX, 0) != MPG123_OK) {
				MPGERROR();
			}
			if (mpg123_open_feed(context->mh) != MPG123_OK) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening mpg feed\n");
				mpg123err = mpg123_strerror(context->mh);
				goto error;
			}
			context->stream_url = switch_core_sprintf(context->memory_pool, "http://%s", path);
			context->prebuf = handle->prebuf;
			launch_read_stream_thread(context);
		} else {
			handle->seekable = 1;
			if (mpg123_param(context->mh, MPG123_FLAGS, MPG123_MONO_MIX, 0) != MPG123_OK) {
				MPGERROR();
			}
			if (mpg123_open(context->mh, path) != MPG123_OK) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
				mpg123err = mpg123_strerror(context->mh);
				goto error;
			}

		}
	} else if (switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
		if (switch_test_flag(handle, SWITCH_FILE_WRITE_APPEND)) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Appending to MP3 not supported.\n");
		}
		if (!(context->gfp = lame_init())) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
			goto error;
		}

		if (!handle->handler) {
			id3tag_init(context->gfp);
			id3tag_v2_only(context->gfp);
			id3tag_pad_v2(context->gfp);

		}
		context->channels = handle->channels;
		lame_set_brate(context->gfp, 16 * (handle->samplerate / 8000) * handle->channels);
		lame_set_num_channels(context->gfp, handle->channels);
		lame_set_in_samplerate(context->gfp, handle->samplerate);
		lame_set_out_samplerate(context->gfp, handle->samplerate);

		if (handle->channels == 2) {
			lame_set_mode(context->gfp, STEREO);
		} else {
			lame_set_mode(context->gfp, MONO);
		}
		lame_set_quality(context->gfp, 2);	/* 2=high  5 = medium  7=low */

		lame_set_errorf(context->gfp, log_error);
		lame_set_debugf(context->gfp, log_debug);
		lame_set_msgf(context->gfp, log_msg);

		if (handle->handler) {
			if (switch_buffer_create_dynamic(&context->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error!\n");
				goto error;
			}
			lame_set_bWriteVbrTag(context->gfp, 0);
			lame_mp3_tags_fid(context->gfp, NULL);

			username = switch_core_strdup(handle->memory_pool, path);
			if (!(password = strchr(username, ':'))) {
				err = "invalid url";
				goto error;
			}
			*password++ = '\0';

			if (!(host = strchr(password, '@'))) {
				err = "invalid url";
				goto error;
			}
			*host++ = '\0';

			if ((file = strchr(host, '/'))) {
				*file++ = '\0';
			} else {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid URL: %s\n", path);
				goto error;
			}

			if ((port = strchr(host, ':'))) {
				*port++ = '\0';
				if (port) {
					portno = atoi(port);
				}
			}

			if (!portno) {
				portno = 8000;
			}

			if (!(context->shout = shout_new())) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate shout_t\n");
				goto error;
			}

			if (shout_set_host(context->shout, host) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting hostname: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_protocol(context->shout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting protocol: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_port(context->shout, portno) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting port: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_password(context->shout, password) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting password: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_mount(context->shout, file) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting mount: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_user(context->shout, username) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting user: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_url(context->shout, "http://www.freeswitch.org") != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_description(context->shout, "FreeSWITCH mod_shout Broadcasting Module") != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting description: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_audio_info(context->shout, "bitrate", "24000") != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting bitrate: %s\n", shout_get_error(context->shout));
				goto error;
			}

			if (shout_set_format(context->shout, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting format: %s\n", shout_get_error(context->shout));
				goto error;
			}

		} else {
			/* lame being lame and all has FILE * coded into it's API for some functions so we gotta use it */
			if (!(context->fp = fopen(path, "wb+"))) {
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening %s\n", path);
				goto error;
			}
		}
	}

	handle->samples = 0;
	handle->format = 0;
	handle->sections = 0;
	handle->speed = 0;
	handle->private_info = context;
	switch_thread_rwlock_unlock(context->rwlock);

	return SWITCH_STATUS_SUCCESS;

  error:
	switch_thread_rwlock_unlock(context->rwlock);
	if (err) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n", err);
	}
	if (mpg123err) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error from mpg123: %s\n", mpg123err);
	}
	free_context(context);
	return SWITCH_STATUS_GENERR;

}
Ejemplo n.º 3
0
Archivo: shout.c Proyecto: CSRedRat/vlc
/*****************************************************************************
 * Open: open the shout connection
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    sout_access_out_t *p_access = (sout_access_out_t*)p_this;
    sout_access_out_sys_t *p_sys;
    shout_t *p_shout;
    long i_ret;
    char *psz_val;

    char *psz_name;
    char *psz_description;
    char *psz_genre;
    char *psz_url;
    vlc_url_t url;

    config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg );

    if( !p_access->psz_path )
    {
        msg_Err( p_access,
                 "please specify url=user:password@host:port/mountpoint" );
        return VLC_EGENERIC;
    }

    vlc_UrlParse( &url , p_access->psz_path, 0 );
    if( url.i_port <= 0 )
        url.i_port = 8000;

    p_sys = p_access->p_sys = malloc( sizeof( sout_access_out_sys_t ) );
    if( !p_sys )
    {
        vlc_UrlClean( &url );
        return VLC_ENOMEM;
    }

    psz_name = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "name" );
    psz_description = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "description" );
    psz_genre = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "genre" );
    psz_url = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "url" );

    p_shout = p_sys->p_shout = shout_new();
    if( !p_shout
         || shout_set_host( p_shout, url.psz_host ) != SHOUTERR_SUCCESS
         || shout_set_protocol( p_shout, SHOUT_PROTOCOL_ICY ) != SHOUTERR_SUCCESS
         || shout_set_port( p_shout, url.i_port ) != SHOUTERR_SUCCESS
         || shout_set_password( p_shout, url.psz_password ) != SHOUTERR_SUCCESS
         || shout_set_mount( p_shout, url.psz_path ) != SHOUTERR_SUCCESS
         || shout_set_user( p_shout, url.psz_username ) != SHOUTERR_SUCCESS
         || shout_set_agent( p_shout, "VLC media player " VERSION ) != SHOUTERR_SUCCESS
         || shout_set_name( p_shout, psz_name ) != SHOUTERR_SUCCESS
         || shout_set_description( p_shout, psz_description ) != SHOUTERR_SUCCESS
         || shout_set_genre( p_shout, psz_genre ) != SHOUTERR_SUCCESS
         || shout_set_url( p_shout, psz_url ) != SHOUTERR_SUCCESS
         /* || shout_set_nonblocking( p_shout, 1 ) != SHOUTERR_SUCCESS */
      )
    {
        msg_Err( p_access, "failed to initialize shout streaming to %s:%i/%s",
                 url.psz_host, url.i_port, url.psz_path );

        free( psz_name );
        free( psz_description );
        free( psz_genre );
        free( psz_url );
        goto error;
    }

    free( psz_name );
    free( psz_description );
    free( psz_genre );
    free( psz_url );

    i_ret = shout_set_format( p_shout, var_GetBool( p_access, SOUT_CFG_PREFIX "mp3" ) ?
                                       SHOUT_FORMAT_MP3 : SHOUT_FORMAT_OGG );

    if( i_ret != SHOUTERR_SUCCESS )
    {
        msg_Err( p_access, "failed to set the shoutcast streaming format" );
        goto error;
    }

    /* Don't force bitrate to 0 but only use when specified. This will otherwise
       show an empty field on icecast directory listing instead of NA */
    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "bitrate" );
    if( psz_val )
    {
        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_BITRATE, psz_val );
        free( psz_val );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the information about the bitrate" );
            goto error;
        }
    }
    else
    {
        /* Bitrate information is used for icecast/shoutcast servers directory
           listings (sorting, stream info etc.) */
        msg_Warn( p_access, "no bitrate information specified (required for listing " \
                            "the server as public on the shoutcast website)" );
    }

    /* Information about samplerate, channels and quality will not be propagated
       through the YP protocol for icecast to the public directory listing when
       the icecast server is operating in shoutcast compatibility mode */

    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "samplerate" );
    if( psz_val )
    {
        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_SAMPLERATE, psz_val );
        free( psz_val );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the information about the samplerate" );
            goto error;
        }
    }

    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "channels" );
    if( psz_val )
    {
        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_CHANNELS, psz_val );
        free( psz_val );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the information about the number of channels" );
            goto error;
        }
    }

    psz_val = var_GetNonEmptyString( p_access, SOUT_CFG_PREFIX "quality" );
    if( psz_val )
    {
        i_ret = shout_set_audio_info( p_shout, SHOUT_AI_QUALITY, psz_val );
        free( psz_val );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the information about Ogg Vorbis quality" );
            goto error;
        }
    }

    if( var_GetBool( p_access, SOUT_CFG_PREFIX "public" ) )
    {
        i_ret = shout_set_public( p_shout, 1 );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the server status setting to public" );
            goto error;
        }
    }

    /* Connect at startup. Cycle through the possible protocols. */
    i_ret = shout_get_connected( p_shout );
    while ( i_ret != SHOUTERR_CONNECTED )
    {
        /* Shout parameters cannot be changed on an open connection */
        i_ret = shout_close( p_shout );
        if( i_ret == SHOUTERR_SUCCESS )
        {
            i_ret = SHOUTERR_UNCONNECTED;
        }

        /* Re-initialize for Shoutcast using ICY protocol. Not needed for initial connection
           but it is when we are reconnecting after other protocol was tried. */
        i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_ICY );
        if( i_ret != SHOUTERR_SUCCESS )
        {
            msg_Err( p_access, "failed to set the protocol to 'icy'" );
            goto error;
        }
        i_ret = shout_open( p_shout );
        if( i_ret == SHOUTERR_SUCCESS )
        {
            i_ret = SHOUTERR_CONNECTED;
            msg_Dbg( p_access, "connected using 'icy' (shoutcast) protocol" );
        }
        else
        {
            msg_Warn( p_access, "failed to connect using 'icy' (shoutcast) protocol" );

            /* Shout parameters cannot be changed on an open connection */
            i_ret = shout_close( p_shout );
            if( i_ret == SHOUTERR_SUCCESS )
            {
                i_ret = SHOUTERR_UNCONNECTED;
            }

            /* IceCAST using HTTP protocol */
            i_ret = shout_set_protocol( p_shout, SHOUT_PROTOCOL_HTTP );
            if( i_ret != SHOUTERR_SUCCESS )
            {
                msg_Err( p_access, "failed to set the protocol to 'http'" );
                goto error;
            }
            i_ret = shout_open( p_shout );
            if( i_ret == SHOUTERR_SUCCESS )
            {
                i_ret = SHOUTERR_CONNECTED;
                msg_Dbg( p_access, "connected using 'http' (icecast 2.x) protocol" );
            }
            else
                msg_Warn( p_access, "failed to connect using 'http' (icecast 2.x) protocol " );
        }
/*
        for non-blocking, use:
        while( i_ret == SHOUTERR_BUSY )
        {
            sleep( 1 );
            i_ret = shout_get_connected( p_shout );
        }
*/
        if ( i_ret != SHOUTERR_CONNECTED )
    	{
    	    msg_Warn( p_access, "unable to establish connection, retrying..." );
            msleep( 30000000 );
        }
    }

    if( i_ret != SHOUTERR_CONNECTED )
    {
        msg_Err( p_access, "failed to open shout stream to %s:%i/%s: %s",
                 url.psz_host, url.i_port, url.psz_path, shout_get_error(p_shout) );
        goto error;
    }

    p_access->pf_write = Write;
    p_access->pf_seek  = Seek;
    p_access->pf_control = Control;

    msg_Dbg( p_access, "shout access output opened (%s@%s:%i/%s)",
             url.psz_username, url.psz_host, url.i_port, url.psz_path );

    vlc_UrlClean( &url );
    return VLC_SUCCESS;

error:
    if( p_sys->p_shout )
        shout_free( p_sys->p_shout );
    vlc_UrlClean( &url );
    free( p_sys );
    return VLC_EGENERIC;
}
Ejemplo n.º 4
0
void EngineShoutcast::updateFromPreferences() {
    qDebug() << "EngineShoutcast: updating from preferences";

    m_pUpdateShoutcastFromPrefs->slotSet(0.0f);

    m_format_is_mp3 = false;
    m_format_is_ov = false;
    m_protocol_is_icecast1 = false;
    m_protocol_is_icecast2 = false;
    m_protocol_is_shoutcast = false;
    m_ogg_dynamic_update = false;

    // Convert a bunch of QStrings to QByteArrays so we can get regular C char*
    // strings to pass to libshout.

    QString codec = m_pConfig->getValueString(ConfigKey(SHOUTCAST_PREF_KEY, "metadata_charset"));
    QByteArray baCodec = codec.toLatin1();
    m_pTextCodec = QTextCodec::codecForName(baCodec);
    if (!m_pTextCodec) {
        qDebug() << "Couldn't find shoutcast metadata codec for codec:" << codec
                 << " defaulting to ISO-8859-1.";
    }

    // Indicates our metadata is in the provided charset.
    shout_metadata_add(m_pShoutMetaData, "charset",  baCodec.constData());

    // Host, server type, port, mountpoint, login, password should be latin1.
    QByteArray baHost = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "host")).toLatin1();
    QByteArray baServerType = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "servertype")).toLatin1();
    QByteArray baPort = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "port")).toLatin1();
    QByteArray baMountPoint = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "mountpoint")).toLatin1();
    QByteArray baLogin = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "login")).toLatin1();
    QByteArray baPassword = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "password")).toLatin1();
    QByteArray baFormat = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "format")).toLatin1();
    QByteArray baBitrate = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "bitrate")).toLatin1();

    // Encode metadata like stream name, website, desc, genre, title/author with
    // the chosen TextCodec.
    QByteArray baStreamName = encodeString(m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "stream_name")));
    QByteArray baStreamWebsite = encodeString(m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "stream_website")));
    QByteArray baStreamDesc = encodeString(m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "stream_desc")));
    QByteArray baStreamGenre = encodeString(m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "stream_genre")));
    QByteArray baStreamPublic = encodeString(m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "stream_public")));

    // Dynamic Ogg metadata update
    m_ogg_dynamic_update = (bool)m_pConfig->getValueString(
	        ConfigKey(SHOUTCAST_PREF_KEY,"ogg_dynamicupdate")).toInt();

    m_custom_metadata = (bool)m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "enable_metadata")).toInt();
    m_customTitle = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "custom_title"));
    m_customArtist = m_pConfig->getValueString(
            ConfigKey(SHOUTCAST_PREF_KEY, "custom_artist"));

    int format;
    int protocol;

    if (shout_set_host(m_pShout, baHost.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting hostname!"), shout_get_error(m_pShout));
        return;
    }

    // WTF? Why SHOUT_PROTOCOL_HTTP and not.. the chosen protocol?
    if (shout_set_protocol(m_pShout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting protocol!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_port(m_pShout, baPort.toUInt()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting port!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_password(m_pShout, baPassword.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting password!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_mount(m_pShout, baMountPoint.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting mount!"), shout_get_error(m_pShout));
        return;
    }


    if (shout_set_user(m_pShout, baLogin.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting username!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_name(m_pShout, baStreamName.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting stream name!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_description(m_pShout, baStreamDesc.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting stream description!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_genre(m_pShout, baStreamGenre.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting stream genre!"), shout_get_error(m_pShout));
        return;
    }

    if (shout_set_url(m_pShout, baStreamWebsite.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting stream url!"), shout_get_error(m_pShout));
        return;
    }

    m_format_is_mp3 = !qstrcmp(baFormat.constData(), SHOUTCAST_FORMAT_MP3);
    m_format_is_ov = !qstrcmp(baFormat.constData(), SHOUTCAST_FORMAT_OV);
    if (m_format_is_mp3) {
        format = SHOUT_FORMAT_MP3;
    } else if (m_format_is_ov) {
        format = SHOUT_FORMAT_OGG;
    } else {
        qDebug() << "Error: unknown format:" << baFormat.constData();
        return;
    }

    if (shout_set_format(m_pShout, format) != SHOUTERR_SUCCESS) {
        errorDialog("Error setting soutcast format!", shout_get_error(m_pShout));
        return;
    }

    bool bitrate_is_int = false;
    int iBitrate = baBitrate.toInt(&bitrate_is_int);

    if (!bitrate_is_int) {
        qDebug() << "Error: unknown bitrate:" << baBitrate.constData();
    }

    int iMasterSamplerate = m_pMasterSamplerate->get();
    if (m_format_is_ov && iMasterSamplerate == 96000) {
        errorDialog(tr("Broadcasting at 96kHz with Ogg Vorbis is not currently "
                       "supported. Please try a different sample-rate or switch "
                       "to a different encoding."),
                    tr("See https://bugs.launchpad.net/mixxx/+bug/686212 for more "
                       "information."));
        return;
    }

    if (shout_set_audio_info(m_pShout, SHOUT_AI_BITRATE, baBitrate.constData()) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting bitrate"), shout_get_error(m_pShout));
        return;
    }

    m_protocol_is_icecast2 = !qstricmp(baServerType.constData(), SHOUTCAST_SERVER_ICECAST2);
    m_protocol_is_shoutcast = !qstricmp(baServerType.constData(), SHOUTCAST_SERVER_SHOUTCAST);
    m_protocol_is_icecast1 = !qstricmp(baServerType.constData(), SHOUTCAST_SERVER_ICECAST1);


    if (m_protocol_is_icecast2) {
        protocol = SHOUT_PROTOCOL_HTTP;
    } else if (m_protocol_is_shoutcast) {
        protocol = SHOUT_PROTOCOL_ICY;
    } else if (m_protocol_is_icecast1) {
        protocol = SHOUT_PROTOCOL_XAUDIOCAST;
    } else {
        errorDialog(tr("Error: unknown server protocol!"), shout_get_error(m_pShout));
        return;
    }

    if (m_protocol_is_shoutcast && !m_format_is_mp3) {
        errorDialog(tr("Error: libshout only supports Shoutcast with MP3 format!"),
                    shout_get_error(m_pShout));
        return;
    }

    if (shout_set_protocol(m_pShout, protocol) != SHOUTERR_SUCCESS) {
        errorDialog(tr("Error setting protocol!"), shout_get_error(m_pShout));
        return;
    }

    // Initialize m_encoder
    if (m_encoder) {
        // delete m_encoder if it has been initalized (with maybe) different bitrate
        delete m_encoder;
        m_encoder = NULL;
    }

    if (m_format_is_mp3) {
        m_encoder = new EncoderMp3(this);
    } else if (m_format_is_ov) {
        m_encoder = new EncoderVorbis(this);
    } else {
        qDebug() << "**** Unknown Encoder Format";
        return;
    }

    if (m_encoder->initEncoder(iBitrate, iMasterSamplerate) < 0) {
        //e.g., if lame is not found
        //init m_encoder itself will display a message box
        qDebug() << "**** Encoder init failed";
        delete m_encoder;
        m_encoder = NULL;
    }
}
Ejemplo n.º 5
0
bool Shouter::apply_profile() {
    char temp[256];
    func("Shouter::apply_profile() on shouter id %i",id);

    bool was_running = running, res = true;
    if(was_running) stop();

    if(shout_set_host(ice,host()))
        error("shout_set_host: %s",shout_get_error(ice));

    if( shout_set_port(ice,port()) )
        error("shout_set_port: %s",shout_get_error(ice));

    if( shout_set_password(ice,pass()) )
        error("shout_set_password: %s",shout_get_error(ice));

    // === fixes the format of the mountpoint
    if((mount())[0]!='/') {
        char tmp[MAX_VALUE_SIZE];
        sprintf(tmp,"/%s",mount());
        mount(tmp);
    }

    // use a .ogg termination on ogg streams
    // this fixes stream codec recognization in xmms et al.
    if(format == SHOUT_FORMAT_VORBIS)
        if(!strstr(mount(),".ogg")) {
            char tmp[MAX_VALUE_SIZE];
            sprintf(tmp,"%s.ogg",mount());
            mount(tmp);
        }


    if( shout_set_mount(ice,mount()) )
        error("shout_set_mount: %s",shout_get_error(ice));

    if( shout_set_name(ice,name()) )
        error("shout_set_name: %s",shout_get_error(ice));

    if( shout_set_url(ice,url()) )
        error("shout_set_url: %s",shout_get_error(ice));

    if( shout_set_description(ice,desc()) )
        error("shout_set_description: %s",shout_get_error(ice));


    //if( shout_set_bitrate(ice,_bps) )
    //  error("shout_set_bitrate: %s",shout_get_error(ice));

    if( shout_set_audio_info(ice, SHOUT_AI_BITRATE, bps()) )
        error("shout_set_audio_info %s: %s",SHOUT_AI_BITRATE, bps());

    if( shout_set_audio_info(ice, SHOUT_AI_SAMPLERATE, freq()) )
        error("shout_set_audio_info %s: %s",SHOUT_AI_SAMPLERATE, freq());

    if( shout_set_audio_info(ice, SHOUT_AI_CHANNELS, channels()) )
        error("shout_set_audio_info %s: %s",SHOUT_AI_CHANNELS, channels());

    func("Shouter audio info: %sKbp/s %sHz %s channels",
         shout_get_audio_info(ice, SHOUT_AI_BITRATE),
         shout_get_audio_info(ice, SHOUT_AI_SAMPLERATE),
         shout_get_audio_info(ice, SHOUT_AI_CHANNELS));

    if( shout_set_protocol(ice,login()) )
        error("shout_set_protocol %i: %s",login(),shout_get_error(ice));

    if( shout_set_format(ice,format) )
        error("shout_set_format: %s",shout_get_error(ice));

    if( shout_set_user(ice,"source") )
        error("shout_set_user: %s",shout_get_error(ice));

    snprintf(temp,256,"%s ver. %s",PACKAGE,VERSION);
    if( shout_set_agent(ice,temp) )
        error("shout_set_agent: %s",shout_get_error(ice));

    snprintf(streamurl,MAX_VALUE_SIZE,
             "http://%s:%i%s",host(),port(),mount());

    if(was_running) {
        res = start();
    }
    profile_changed = false;
    return res;
}
Ejemplo n.º 6
0
shout_t *
stream_setup(const char *host, unsigned short port, const char *mount)
{
	shout_t *shout = NULL;

	if ((shout = shout_new()) == NULL) {
		printf("%s: shout_new(): %s", __progname, strerror(ENOMEM));
		return (NULL);
	}

	if (shout_set_host(shout, host) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_host(): %s\n", __progname,
		       shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (shout_set_protocol(shout, SHOUT_PROTOCOL_HTTP) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_protocol(): %s\n", __progname,
			shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (shout_set_port(shout, port) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_port: %s\n", __progname,
			shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (shout_set_password(shout, pezConfig->password) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_password(): %s\n", __progname,
			shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (shout_set_mount(shout, mount) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_mount(): %s\n", __progname,
			shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (shout_set_user(shout, "source") != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_user(): %s\n", __progname,
			shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}

	if (!strcmp(pezConfig->format, MP3_FORMAT) &&
	    shout_set_format(shout, SHOUT_FORMAT_MP3) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_format(MP3): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if ((!strcmp(pezConfig->format, VORBIS_FORMAT) ||
	     !strcmp(pezConfig->format, THEORA_FORMAT)) &&
	    shout_set_format(shout, SHOUT_FORMAT_OGG) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_format(OGG): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}

	if (pezConfig->username &&
	    shout_set_user(shout, pezConfig->username) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_user(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverName &&
	    shout_set_name(shout, pezConfig->serverName) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_name(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverURL &&
	    shout_set_url(shout, pezConfig->serverURL) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_url(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverGenre &&
	    shout_set_genre(shout, pezConfig->serverGenre) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_genre(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverDescription &&
	    shout_set_description(shout, pezConfig->serverDescription) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_description(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverBitrate &&
	    shout_set_audio_info(shout, SHOUT_AI_BITRATE, pezConfig->serverBitrate) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_audio_info(AI_BITRATE): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverChannels &&
	    shout_set_audio_info(shout, SHOUT_AI_CHANNELS, pezConfig->serverChannels) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_audio_info(AI_CHANNELS): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverSamplerate &&
	    shout_set_audio_info(shout, SHOUT_AI_SAMPLERATE, pezConfig->serverSamplerate) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_audio_info(AI_SAMPLERATE): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}
	if (pezConfig->serverQuality &&
	    shout_set_audio_info(shout, SHOUT_AI_QUALITY, pezConfig->serverQuality) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_audio_info(AI_QUALITY): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}

	if (shout_set_public(shout, (unsigned int)pezConfig->serverPublic) != SHOUTERR_SUCCESS) {
		printf("%s: shout_set_public(): %s\n",
		       __progname, shout_get_error(shout));
		shout_free(shout);
		return (NULL);
	}

	return (shout);
}
Ejemplo n.º 7
0
static SCM open_vorbis_stream(SCM server, SCM port, SCM password,
			SCM mount, SCM config) {
	SCM smob;
	double qual;
	char stream_name[32];
	VORBIS_STREAM *stream;
	stream = (VORBIS_STREAM *)my_gc_malloc(sizeof(VORBIS_STREAM),
				"vorbis_stream", "vorbis stream");
	stream->header.shutdown = vorbis_shutdown;
	vorbis_info_init(&(stream->vi));
	SCM quality = get_property(config, "quality");
	if (scm_is_number(quality)) qual = scm_to_double(quality);
	else qual = 0.6;
	scm_remember_upto_here_1(quality);
	stream->header.shoutbuf = NULL;
	stream->header.shoutbuf_size = 0;
	stream->header.rb_size = sizeof(sample_t) * RB_SECS * sampling_rate 
				* QMX_CHANNELS + 0.5;
	stream->header.ringbuf = jack_ringbuffer_create(stream->header.rb_size);
	if (vorbis_encode_init_vbr(&(stream->vi), QMX_CHANNELS,
				sampling_rate, qual) != 0) {
		log_msg("vorbis init failed\n");
		return SCM_BOOL_F;
		}
	if ((stream->header.shout = shout_new()) == NULL) {
		log_msg("can't create shout instance\n");
		return SCM_BOOL_F;
		}
	vorbis_analysis_init(&(stream->vd), &(stream->vi));
	vorbis_block_init(&(stream->vd), &(stream->vb));
	ogg_stream_init(&(stream->os), rand());
	vorbis_comment_init(&(stream->vc));
	vorbis_comment_add_tag(&(stream->vc), "ENCODER", "QMX");
	shout_set_protocol(stream->header.shout, SHOUT_PROTOCOL_HTTP);
	shout_set_format(stream->header.shout, SHOUT_FORMAT_OGG);
	char *server_s = scm_to_locale_string(server); // server
	shout_set_host(stream->header.shout, server_s);
	free(server_s);
	shout_set_port(stream->header.shout, scm_to_int(port)); // port
	shout_set_user(stream->header.shout, "source"); // user
	char *password_s = scm_to_locale_string(password); // password
	shout_set_password(stream->header.shout, password_s);
	free(password_s);
	char *mount_s = scm_to_locale_string(mount); // mount pt
	shout_set_mount(stream->header.shout, mount_s);
	SCM title = get_property(config, "title");
	if (scm_is_string(title)) {
		char *title_s = scm_to_locale_string(title);
		if (strlen(title_s) > 0)
			vorbis_comment_add_tag(&(stream->vc), "TITLE", title_s);
		free(title_s);
		}
	scm_remember_upto_here_1(title);
	SCM name = get_property(config, "name");
	stream_name[0] = '\0';
	if (scm_is_string(name)) {
		char *name_s = scm_to_locale_string(name);
		shout_set_name(stream->header.shout, name_s);
		snprintf(stream_name, sizeof(stream_name), "'%s' ", name_s);
		free(name_s);
		}
	scm_remember_upto_here_1(name);
	SCM description = get_property(config, "description");
	if (scm_is_string(description)) {
		char *description_s = scm_to_locale_string(description);
		shout_set_description(stream->header.shout, description_s);
		free(description_s);
		}
	scm_remember_upto_here_1(description);
	SCM genre = get_property(config, "genre");
	if (scm_is_string(genre)) {
		char *genre_s = scm_to_locale_string(genre);
		shout_set_genre(stream->header.shout, genre_s);
		free(genre_s);
		}
	scm_remember_upto_here_1(genre);
	shout_set_audio_info(stream->header.shout,
			SHOUT_AI_CHANNELS, encode_int(QMX_CHANNELS));
	shout_set_audio_info(stream->header.shout,
			SHOUT_AI_SAMPLERATE, encode_int(sampling_rate));
	if (shout_open(stream->header.shout) == SHOUTERR_SUCCESS) {
		log_msg("vorbis stream %smounted at %s\n", stream_name, mount_s);
		free(mount_s);
		}
	else {
		log_msg("vorbis stream %sfailed to open: %s\n", stream_name,
				shout_get_error(stream->header.shout));
		free(mount_s);
		shout_free(stream->header.shout);
		return SCM_BOOL_F;
		}
	vorbis_streams += 1;
	stream->header.eos = 0;
	SCM_NEWSMOB(smob, vorbis_stream_tag, stream);
	streams = link_in(streams, smob);
	stream->header.do_prep = need_prepper;
	need_prepper = 0;
	stream->header.bookmark = 0;
	add_outbuf_client(load_frames, process_frames, (void *)stream,
						"Ogg-Vorbis stream");
	spawn_detached_thread(shout_thread, (void *)&(stream->header));
	scm_remember_upto_here_1(smob);
	return smob;
	}
Ejemplo n.º 8
0
/* The main loop for each instance. Gets data passed to it from the stream
 * manager (which gets it from the input module), and streams it to the
 * specified server
 */
void *ices_instance_stream(void *arg)
{
    int ret, shouterr;
    ref_buffer *buffer;
    stream_description *sdsc = arg;
    instance_t *stream = sdsc->stream;
    input_module_t *inmod = sdsc->input;
    int reencoding = (inmod->type == ICES_INPUT_VORBIS) && stream->encode;
    int encoding = (inmod->type == ICES_INPUT_PCM) && stream->encode;
    char *stream_name = NULL, *stream_genre = NULL, *stream_description = NULL;
    char *stream_url = NULL, *user = NULL;
    char audio_info[11];
    
    vorbis_comment_init(&sdsc->vc);

    sdsc->shout = shout_new();

    /* we only support the ice protocol and vorbis streams currently */
    shout_set_format(sdsc->shout, SHOUT_FORMAT_VORBIS);
    shout_set_protocol(sdsc->shout, SHOUT_PROTOCOL_HTTP);

    signal(SIGPIPE, signal_hup_handler);

    if (!(shout_set_host(sdsc->shout, stream->hostname)) == SHOUTERR_SUCCESS) {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }

    shout_set_port(sdsc->shout, stream->port);
    if (!(shout_set_password(sdsc->shout, stream->password)) == SHOUTERR_SUCCESS) {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }
    if (stream->user)
        user = stream->user;
    else
        user = "******";

    if(shout_set_user(sdsc->shout, user) != SHOUTERR_SUCCESS) {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }

    if (!(shout_set_agent(sdsc->shout, PACKAGE_STRING)) == SHOUTERR_SUCCESS) {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }

    if (!(shout_set_mount(sdsc->shout, stream->mount)) == SHOUTERR_SUCCESS) {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }
    if (shout_set_public (sdsc->shout, stream->public_stream & 1) != SHOUTERR_SUCCESS)
    {
        LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
        stream->died = 1;
        return NULL;
    }

    /* set the metadata for the stream */
    if(stream->stream_name)
        stream_name = stream->stream_name;
    else if (ices_config->stream_name)
        stream_name = ices_config->stream_name;

    if(stream->stream_description)
        stream_description = stream->stream_description;
    else if (ices_config->stream_description)
        stream_description = ices_config->stream_description;

    if(stream->stream_genre)
        stream_genre = stream->stream_genre;
    else if (ices_config->stream_genre)
        stream_genre = ices_config->stream_genre;

    if(stream->stream_url)
        stream_url = stream->stream_url;
    else if (ices_config->stream_url)
        stream_url = ices_config->stream_url;

    if(stream_name)
        if (!(shout_set_name(sdsc->shout, stream_name)) == SHOUTERR_SUCCESS) {
            LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
            stream->died = 1;
            return NULL;
        }
    if (stream_genre)
        if (!(shout_set_genre(sdsc->shout, stream_genre)) == SHOUTERR_SUCCESS) {
            LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
            stream->died = 1;
            return NULL;
        }
    if (stream_description)
        if (!(shout_set_description(sdsc->shout, stream_description)) == SHOUTERR_SUCCESS) {
            LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
            stream->died = 1;
            return NULL;
        }
    if (stream_url)
        if (!(shout_set_url(sdsc->shout, stream_url) == SHOUTERR_SUCCESS)) {
            LOG_ERROR1("libshout error: %s\n", shout_get_error(sdsc->shout));
            stream->died = 1;
            return NULL;
        }

    if(stream->downmix && encoding && stream->channels == 1) {
        stream->channels = 1;
        sdsc->downmix = downmix_initialise();
    }

    if(stream->resampleinrate && stream->resampleoutrate && encoding) {
        stream->samplerate = stream->resampleoutrate;
        sdsc->resamp = resample_initialise(stream->channels, 
                stream->resampleinrate, stream->resampleoutrate);
    }

    /* max integer is 10 bytes + 1 for null term */
    snprintf(audio_info, sizeof(audio_info), "%d", stream->samplerate);
    shout_set_audio_info(sdsc->shout, SHOUT_AI_SAMPLERATE, audio_info);
    snprintf(audio_info, sizeof(audio_info), "%d", stream->channels);
    shout_set_audio_info(sdsc->shout, SHOUT_AI_CHANNELS, audio_info);
    if (stream->managed)
    {
        snprintf(audio_info, sizeof(audio_info), "%d", stream->nom_br/1000);
        shout_set_audio_info(sdsc->shout, SHOUT_AI_BITRATE, audio_info);
    }
    else
    {
        snprintf(audio_info, sizeof(audio_info), "%2.2f", stream->quality);
        shout_set_audio_info(sdsc->shout, SHOUT_AI_QUALITY, audio_info);
    }

    if(encoding)
    {
        if(inmod->metadata_update)
            inmod->metadata_update(inmod->internal, &sdsc->vc);
        sdsc->enc = encode_initialise(stream->channels, stream->samplerate,
                stream->managed, stream->min_br, stream->nom_br, stream->max_br,
                stream->quality, &sdsc->vc);
        if(!sdsc->enc) {
            LOG_ERROR0("Failed to configure encoder");
            stream->died = 1;
            return NULL; /* FIXME: probably leaking some memory here */
        }
    }
    else if(reencoding)
        sdsc->reenc = reencode_init(stream);

    if(stream->savefilename != NULL) 
    {
        stream->savefile = fopen(stream->savefilename, "wb");
        if(!stream->savefile)
            LOG_ERROR2("Failed to open stream save file %s: %s", 
                    stream->savefilename, strerror(errno));
        else
            LOG_INFO1("Saving stream to file %s", stream->savefilename);
    }

    if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
    {
        LOG_INFO3("Connected to server: %s:%d%s", 
                shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), shout_get_mount(sdsc->shout));

        while(1)
        {
            if(stream->buffer_failures > MAX_ERRORS)
            {
                LOG_WARN0("Too many errors, shutting down");
                break;
            }

            buffer = stream_wait_for_data(stream);

            /* buffer being NULL means that either a fatal error occured,
             * or we've been told to shut down
             */
            if(!buffer)
                break;

            /* If data is NULL or length is 0, we should just skip this one.
             * Probably, we've been signalled to shut down, and that'll be
             * caught next iteration. Add to the error count just in case,
             * so that we eventually break out anyway 
             */
            if(!buffer->buf || !buffer->len)
            {
                LOG_WARN0("Bad buffer dequeued!");
                stream->buffer_failures++;
                continue; 
            }

            if(stream->wait_for_critical)
            {
                LOG_INFO0("Trying restart on new substream");
                stream->wait_for_critical = 0;
            }

            ret = process_and_send_buffer(sdsc, buffer);

            /* No data produced, do nothing */
            if(ret == -1)
                ;
            /* Fatal error */
            else if(ret == -2)
            {
                LOG_ERROR0("Serious error, waiting to restart on "
                           "next substream. Stream temporarily suspended.");
                /* Set to wait until a critical buffer comes through (start of
                 * a new substream, typically), and flush existing queue.
                 */
                thread_mutex_lock(&ices_config->flush_lock);
                stream->wait_for_critical = 1;
                input_flush_queue(stream->queue, 0);
                thread_mutex_unlock(&ices_config->flush_lock);
            }
            /* Non-fatal shout error */
            else if(ret == 0)
            {
                LOG_ERROR2("Send error: %s (%s)", 
                        shout_get_error(sdsc->shout), strerror(errno));
                if(shout_get_errno(sdsc->shout) == SHOUTERR_SOCKET)
                {
                    int i=0;

                    /* While we're trying to reconnect, don't receive data
                     * to this instance, or we'll overflow once reconnect
                     * succeeds
                     */
                    thread_mutex_lock(&ices_config->flush_lock);
                    stream->skip = 1;

                    /* Also, flush the current queue */
                    input_flush_queue(stream->queue, 1);
                    thread_mutex_unlock(&ices_config->flush_lock);
                    
                    while((i < stream->reconnect_attempts ||
                            stream->reconnect_attempts==-1) && 
                            !ices_config->shutdown)
                    {
                        i++;
                        LOG_WARN0("Trying reconnect after server socket error");
                        shout_close(sdsc->shout);
                        if((shouterr = shout_open(sdsc->shout)) == SHOUTERR_SUCCESS)
                        {
                            LOG_INFO3("Connected to server: %s:%d%s", 
                                    shout_get_host(sdsc->shout), shout_get_port(sdsc->shout), 
                                    shout_get_mount(sdsc->shout));
                            /* This stream can't restart until the next
                             * logical stream comes along, since the
                             * server won't have any cached headers for
                             * this source/connection. So, don't continue
                             * yet.
                             */
                            thread_mutex_lock(&ices_config->flush_lock);
                            stream->wait_for_critical = 1;
                            input_flush_queue(stream->queue, 0);
                            thread_mutex_unlock(&ices_config->flush_lock);
                            break;
                        }
                        else
                        {
                            LOG_ERROR3("Failed to reconnect to %s:%d (%s)",
                                shout_get_host(sdsc->shout),shout_get_port(sdsc->shout),
                                shout_get_error(sdsc->shout));
                            if(i==stream->reconnect_attempts)
                            {
                                LOG_ERROR0("Reconnect failed too many times, "
                                          "giving up.");
                                /* We want to die now */
                                stream->buffer_failures = MAX_ERRORS+1; 
                            }
                            else /* Don't try again too soon */
                                thread_sleep (stream->reconnect_delay*1000000); 
                        }
                    }
                    stream->skip = 0;
                }
                stream->buffer_failures++;
            }
            stream_release_buffer(buffer);
        }
    }
    else
    {
        LOG_ERROR4("Failed initial connect to %s:%d (%s: %s)", 
                shout_get_host(sdsc->shout),shout_get_port(sdsc->shout), shout_get_error(sdsc->shout), strerror(errno));
    }
    
    shout_close(sdsc->shout);

    if(stream->savefile != NULL) 
        fclose(stream->savefile);

    shout_free(sdsc->shout);
    encode_clear(sdsc->enc);
    reencode_clear(sdsc->reenc);
    downmix_clear(sdsc->downmix);
    resample_clear(sdsc->resamp);
    vorbis_comment_clear(&sdsc->vc);

    stream->died = 1;
    return NULL;
}