[Freeswitch-svn] [commit] r4511 - freeswitch/trunk/src/mod/formats/mod_shout

Freeswitch SVN brian at freeswitch.org
Sat Mar 10 22:09:36 EST 2007


Author: brian
Date: Sat Mar 10 22:09:36 2007
New Revision: 4511

Added:
   freeswitch/trunk/src/mod/formats/mod_shout/
   freeswitch/trunk/src/mod/formats/mod_shout/Makefile
   freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c

Log:
check in mod_shout can only write so far still gotta add read

Added: freeswitch/trunk/src/mod/formats/mod_shout/Makefile
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_shout/Makefile	Sat Mar 10 22:09:36 2007
@@ -0,0 +1,19 @@
+LDFLAGS += -lshout -lmp3lame
+MOD_CFLAGS += "-I${PREFIX}/include"
+MOD_LDFLAGS += "-L${PREFIX}/lib"
+all:	depends $(MODNAME).$(DYNAMIC_LIB_EXTEN)
+
+depends:
+	MAKE=$(MAKE) $(BASE)/build/buildlib.sh $(BASE) install lame-3.97.tar.gz --prefix=$(PREFIX) --disable-shared --with-pic
+	MOD_CFLAGS="${MOD_CFLAGS}" MOD_LDFLAGS="${LD_CFLAGS}" MAKE=$(MAKE) $(BASE)/build/buildlib.sh $(BASE) install libshout-2.2.2.tar.gz --disable-shared --with-pic --prefix=$(PREFIX)
+
+$(MODNAME).$(DYNAMIC_LIB_EXTEN): $(MODNAME).c
+	$(CC) $(CFLAGS) -fPIC -c $(MODNAME).c -o $(MODNAME).o 
+	$(CC) $(SOLINK) -o $(MODNAME).$(DYNAMIC_LIB_EXTEN)  $(MODNAME).o $(LDFLAGS)
+
+
+clean:
+	rm -fr *.$(DYNAMIC_LIB_EXTEN) *.o *~
+
+install:
+	cp -f $(MODNAME).$(DYNAMIC_LIB_EXTEN) $(PREFIX)/mod

Added: freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c
==============================================================================
--- (empty file)
+++ freeswitch/trunk/src/mod/formats/mod_shout/mod_shout.c	Sat Mar 10 22:09:36 2007
@@ -0,0 +1,401 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct at yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthmct at yahoo.com>
+ *
+ * mod_shout.c -- Icecast Module
+ *
+ * example filename: shout://user:pass@host.com/mount.mp3
+ *
+ */
+#include <switch.h>
+#include <shout/shout.h>
+#include <lame/lame.h>
+
+static const char modname[] = "mod_shout";
+
+
+static char *supported_formats[SWITCH_MAX_CODECS] = {0};
+
+struct shout_context {
+	shout_t *shout;
+    lame_global_flags *gfp;
+};
+
+typedef struct shout_context shout_context_t;
+
+static inline void free_context(shout_context_t *context)
+{
+    if (context) {
+        if (context->shout) {
+            shout_close(context->shout);
+            context->shout = NULL;
+        }
+        if (context->gfp) {
+            lame_close(context->gfp);
+            context->gfp = NULL;
+        }
+    }
+}
+
+
+static void log_error(char const *fmt, va_list ap)
+{
+	char *data = NULL;
+
+	if (fmt) {
+#ifdef HAVE_VASPRINTF
+		int ret;
+		ret = vasprintf(&data, fmt, ap);
+		if ((ret == -1) || !data) {
+			return;
+		}
+#else
+		data = (char *) malloc(2048);
+		if (data) {
+			vsnprintf(data, 2048, fmt, ap);
+		} else { 
+			return;
+		}
+#endif
+	}
+	if (data) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, (char*) "%s", data);
+		free(data);
+	}
+}
+
+static void log_debug(char const *fmt, va_list ap)
+{
+	char *data = NULL;
+
+	if (fmt) {
+#ifdef HAVE_VASPRINTF
+		int ret;
+		ret = vasprintf(&data, fmt, ap);
+		if ((ret == -1) || !data) {
+			return;
+		}
+#else
+		data = (char *) malloc(2048);
+		if (data) {
+			vsnprintf(data, 2048, fmt, ap);
+		} else { 
+			return;
+		}
+#endif
+	}
+	if (data) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, (char*) "%s", data);
+		free(data);
+	}
+}
+
+static void log_msg(char const *fmt, va_list ap)
+{
+	char *data = NULL;
+
+	if (fmt) {
+#ifdef HAVE_VASPRINTF
+		int ret;
+		ret = vasprintf(&data, fmt, ap);
+		if ((ret == -1) || !data) {
+			return;
+		}
+#else
+		data = (char *) malloc(2048);
+		if (data) {
+			vsnprintf(data, 2048, fmt, ap);
+		} else { 
+			return;
+		}
+#endif
+	}
+	if (data) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, (char*) "%s", data);
+		free(data);
+	}
+}
+
+
+static switch_status_t shout_file_open(switch_file_handle_t *handle, char *path)
+{
+	shout_context_t *context;
+    char *host, *file;
+    char *username, *password;
+    char *err = NULL;
+
+    if (switch_test_flag(handle, SWITCH_FILE_FLAG_READ)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read not currently supported.\n");
+        return SWITCH_STATUS_GENERR;
+    }
+
+    if (!switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Only write is supported.\n");
+        return SWITCH_STATUS_GENERR;
+    }
+
+	if ((context = switch_core_alloc(handle->memory_pool, sizeof(*context))) == 0) {
+		return SWITCH_STATUS_MEMERR;
+	}
+
+	if (!(context->shout = shout_new())) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate shout_t\n");
+		goto error;
+	}
+
+    if (!(context->gfp = lame_init())) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate lame\n");
+        goto error;
+    }
+
+    lame_set_num_channels(context->gfp, handle->channels);
+    lame_set_in_samplerate(context->gfp, handle->samplerate);
+    lame_set_brate(context->gfp, 24);
+    lame_set_mode(context->gfp, 3);
+    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);
+    lame_set_bWriteVbrTag(context->gfp, 0);
+    lame_mp3_tags_fid(context->gfp, NULL);
+    lame_init_params(context->gfp);
+    lame_print_config(context->gfp);
+
+    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);
+    }
+
+	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, 8000) != 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, "mod_shout") != 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_audio_info(context->shout, "bitrate", "24000") != 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_format(context->shout, SHOUT_FORMAT_MP3) != 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_open(context->shout) != SHOUTERR_SUCCESS) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error opening stream: %s\n", shout_get_error(context->shout));
+		goto error;
+    }
+
+	handle->private_info = context;
+
+	return SWITCH_STATUS_SUCCESS;
+    
+ error:
+    if (err) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n", err);
+    }
+    free_context(context);
+    return SWITCH_STATUS_GENERR;
+
+}
+
+static switch_status_t shout_file_close(switch_file_handle_t *handle)
+{
+	shout_context_t *context = handle->private_info;
+
+    
+    free_context(context);
+
+	return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t shout_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
+{
+	shout_context_t *context = handle->private_info;
+	
+	return SWITCH_STATUS_FALSE;
+
+}
+
+static switch_status_t shout_file_read(switch_file_handle_t *handle, void *data, size_t *len)
+{
+	shout_context_t *context = handle->private_info;
+
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t shout_file_write(switch_file_handle_t *handle, void *data, size_t *len)
+{
+	shout_context_t *context = handle->private_info;
+
+
+    char mp3buf[2048] = "";
+    long ret = 0;
+    int rlen;
+    int16_t *audio = data;
+    int nsamples = *len;
+
+    if ((rlen = lame_encode_buffer(context->gfp, audio, NULL, nsamples, mp3buf, sizeof(mp3buf))) < 0) {
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MP3 encode error %d!\n", rlen);
+        return SWITCH_STATUS_FALSE;
+    }
+
+    if (rlen) {
+        ret = shout_send(context->shout, mp3buf, rlen);
+        if (ret != SHOUTERR_SUCCESS) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Send error: %s\n", shout_get_error(context->shout));
+            return SWITCH_STATUS_FALSE;
+        }
+    }
+    shout_sync(context->shout);
+
+    return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t shout_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
+{
+	shout_context_t *context = handle->private_info;
+
+    switch(col) {
+    case SWITCH_AUDIO_COL_STR_TITLE:
+        if (shout_set_name(context->shout, string) != SHOUTERR_SUCCESS) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
+        }
+        break;
+    case SWITCH_AUDIO_COL_STR_COMMENT:
+        if (shout_set_url(context->shout, string) != SHOUTERR_SUCCESS) {
+            switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error setting name: %s\n", shout_get_error(context->shout));
+        }
+        break;
+    default:
+        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Value Ignored\n");
+        break;
+    }
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_status_t shout_file_get_string(switch_file_handle_t *handle, switch_audio_col_t col, const char **string)
+{
+	return SWITCH_STATUS_FALSE;
+}
+
+static switch_file_interface_t shout_file_interface = {
+	/*.interface_name */ modname,
+	/*.file_open */ shout_file_open,
+	/*.file_close */ shout_file_close,
+	/*.file_read */ shout_file_read,
+	/*.file_write */ shout_file_write,
+	/*.file_seek */ shout_file_seek,
+	/*.file_set_string */ shout_file_set_string,
+	/*.file_get_string */ shout_file_get_string,
+	/*.extens */ NULL,
+	/*.next */ NULL,
+};
+
+static switch_loadable_module_interface_t shout_module_interface = {
+	/*.module_name */ modname,
+	/*.endpoint_interface */ NULL,
+	/*.timer_interface */ NULL,
+	/*.dialplan_interface */ NULL,
+	/*.codec_interface */ NULL,
+	/*.application_interface */ NULL,
+	/*.api_interface */ NULL,
+	/*.file_interface */ &shout_file_interface,
+	/*.speech_interface */ NULL,
+	/*.directory_interface */ NULL
+};
+
+SWITCH_MOD_DECLARE(switch_status_t) switch_module_load(const switch_loadable_module_interface_t **module_interface, char *filename)
+{
+    supported_formats[0] = "shout";
+	shout_file_interface.extens = supported_formats;
+
+	/* connect my internal structure to the blank pointer passed to me */
+	*module_interface = &shout_module_interface;
+
+	shout_init();
+
+	/* indicate that the module should continue to be loaded */
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:nil
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
+ */



More information about the Freeswitch-svn mailing list