]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
snapshot
authorAnthony Minessale <anthony.minessale@gmail.com>
Fri, 30 Oct 2009 22:56:08 +0000 (22:56 +0000)
committerAnthony Minessale <anthony.minessale@gmail.com>
Fri, 30 Oct 2009 22:56:08 +0000 (22:56 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@15298 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/applications/mod_snapshot/mod_snapshot.2008.vcproj [new file with mode: 0644]
src/mod/applications/mod_snapshot/mod_snapshot.c [new file with mode: 0644]

diff --git a/src/mod/applications/mod_snapshot/mod_snapshot.2008.vcproj b/src/mod/applications/mod_snapshot/mod_snapshot.2008.vcproj
new file mode 100644 (file)
index 0000000..0dea8b2
--- /dev/null
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+       ProjectType="Visual C++"\r
+       Version="9.00"\r
+       Name="mod_snapshot"\r
+       ProjectGUID="{11C9BC3D-45E9-46E3-BE84-B8CEE4685E39}"\r
+       RootNamespace="mod_snapshot"\r
+       Keyword="Win32Proj"\r
+       TargetFrameworkVersion="131072"\r
+       >\r
+       <Platforms>\r
+               <Platform\r
+                       Name="Win32"\r
+               />\r
+               <Platform\r
+                       Name="x64"\r
+               />\r
+       </Platforms>\r
+       <ToolFiles>\r
+       </ToolFiles>\r
+       <Configurations>\r
+               <Configuration\r
+                       Name="Debug|Win32"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               UsePrecompiledHeader="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Debug|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="..\..\..\..\w32\module_debug.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               UsePrecompiledHeader="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|Win32"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               UsePrecompiledHeader="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+               <Configuration\r
+                       Name="Release|x64"\r
+                       OutputDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"\r
+                       ConfigurationType="2"\r
+                       InheritedPropertySheets="..\..\..\..\w32\module_release.vsprops"\r
+                       CharacterSet="2"\r
+                       >\r
+                       <Tool\r
+                               Name="VCPreBuildEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCustomBuildTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXMLDataGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCWebServiceProxyGeneratorTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCMIDLTool"\r
+                               TargetEnvironment="3"\r
+                       />\r
+                       <Tool\r
+                               Name="VCCLCompilerTool"\r
+                               UsePrecompiledHeader="0"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManagedResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCResourceCompilerTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPreLinkEventTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCLinkerTool"\r
+                               OutputFile="$(SolutionDir)$(PlatformName)\$(ConfigurationName)/mod/$(ProjectName).dll"\r
+                               RandomizedBaseAddress="1"\r
+                               DataExecutionPrevention="0"\r
+                               TargetMachine="17"\r
+                       />\r
+                       <Tool\r
+                               Name="VCALinkTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCManifestTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCXDCMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCBscMakeTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCFxCopTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCAppVerifierTool"\r
+                       />\r
+                       <Tool\r
+                               Name="VCPostBuildEventTool"\r
+                       />\r
+               </Configuration>\r
+       </Configurations>\r
+       <References>\r
+       </References>\r
+       <Files>\r
+               <File\r
+                       RelativePath=".\mod_snapshot.c"\r
+                       >\r
+               </File>\r
+       </Files>\r
+       <Globals>\r
+       </Globals>\r
+</VisualStudioProject>\r
diff --git a/src/mod/applications/mod_snapshot/mod_snapshot.c b/src/mod/applications/mod_snapshot/mod_snapshot.c
new file mode 100644 (file)
index 0000000..fb3fcfe
--- /dev/null
@@ -0,0 +1,341 @@
+/* 
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2009, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * 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 <anthm@freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * 
+ * Anthony Minessale II <anthm@freeswitch.org>
+ *
+ *
+ * mod_snapshot.c -- record a sliding window of audio and take snapshots to disk
+ *
+ */
+#include <switch.h>
+
+/* Prototypes */
+SWITCH_MODULE_RUNTIME_FUNCTION(mod_snapshot_runtime);
+SWITCH_MODULE_LOAD_FUNCTION(mod_snapshot_load);
+
+/* SWITCH_MODULE_DEFINITION(name, load, shutdown, runtime) 
+ * Defines a switch_loadable_module_function_table_t and a static const char[] modname
+ */
+SWITCH_MODULE_DEFINITION(mod_snapshot, mod_snapshot_load, NULL, NULL);
+
+struct cap_cb {
+       switch_buffer_t *buffer;
+       switch_mutex_t *mutex;
+       char *base;
+};
+
+static switch_bool_t capture_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type)
+{
+       switch_core_session_t *session = switch_core_media_bug_get_session(bug);
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       struct cap_cb *cb = (struct cap_cb *) user_data;
+
+       switch (type) {
+       case SWITCH_ABC_TYPE_INIT:
+               break;
+       case SWITCH_ABC_TYPE_CLOSE:
+               {
+                       if (cb->buffer) {
+                               switch_buffer_destroy(&cb->buffer);
+                       }
+                       switch_channel_set_private(channel, "snapshot", NULL);
+               }
+
+               break;
+       case SWITCH_ABC_TYPE_READ:
+               
+               if (cb->buffer) {
+                       uint8_t data[SWITCH_RECOMMENDED_BUFFER_SIZE];
+                       switch_frame_t frame = { 0 };
+
+                       frame.data = data;
+                       frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
+                       
+                       if (switch_mutex_trylock(cb->mutex) == SWITCH_STATUS_SUCCESS) {
+                               while (switch_core_media_bug_read(bug, &frame, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS && !switch_test_flag((&frame), SFF_CNG)) {
+                                       if (frame.datalen) switch_buffer_slide_write(cb->buffer, frame.data, frame.datalen);
+                               }
+                               switch_mutex_unlock(cb->mutex);
+                       }
+
+               }
+               break;
+       case SWITCH_ABC_TYPE_WRITE:
+       default:
+               break;
+       }
+
+       return SWITCH_TRUE;
+}
+
+static switch_status_t start_capture(switch_core_session_t *session, unsigned int seconds, switch_media_bug_flag_t flags, const char *base)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_media_bug_t *bug;
+       switch_status_t status;
+       switch_codec_implementation_t read_impl = {0};
+       struct cap_cb *cb;
+       switch_size_t bytes;
+       switch_bind_flag_t bind_flags = 0;
+
+       if (switch_channel_get_private(channel, "snapshot")) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Already Running.\n");
+               return SWITCH_STATUS_FALSE;
+       }
+
+       if (seconds < 5) {
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Must be at least 5 seconds!\n");
+               return SWITCH_STATUS_FALSE;
+       }
+       
+    switch_core_session_get_read_impl(session, &read_impl);
+
+       if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) {
+               return SWITCH_STATUS_FALSE;
+       }
+
+       cb = switch_core_session_alloc(session, sizeof(*cb));
+       cb->base = switch_core_session_strdup(session, base);
+       
+       bytes = read_impl.samples_per_second * seconds * 2;
+
+       switch_buffer_create_dynamic(&cb->buffer, bytes, bytes, bytes);
+       switch_mutex_init(&cb->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+
+       if ((status = switch_core_media_bug_add(session, capture_callback, cb, 0, flags, &bug)) != SWITCH_STATUS_SUCCESS) {
+               return status;
+       }
+
+       bind_flags = SBF_DIAL_ALEG | SBF_EXEC_ALEG | SBF_EXEC_SAME;
+       switch_ivr_bind_dtmf_meta_session(session, 7, bind_flags, "snapshot::snap");
+
+       switch_channel_set_private(channel, "snapshot", bug);
+       
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static void do_snap(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_media_bug_t *bug = switch_channel_get_private(channel, "snapshot");
+       char *file;
+       switch_file_handle_t fh = {0};
+       switch_codec_implementation_t read_impl = {0};
+       switch_size_t bytes_read;
+       int16_t pdata[4096] = {0};
+               
+       if (bug) {
+               switch_time_exp_t tm;
+               switch_size_t retsize;
+               char date[80] = "";
+               struct cap_cb *cb = (struct cap_cb *) switch_core_media_bug_get_user_data(bug);
+
+               if (!cb) {
+                       return;
+               }
+
+               switch_time_exp_lt(&tm, switch_time_make(switch_epoch_time_now(NULL), 0));
+               switch_strftime(date, &retsize, sizeof(date), "%Y_%m_%d_%H_%M_%S", &tm);
+                       
+               file = switch_core_session_sprintf(session, "%s%ssounds%s%s_%s.wav", SWITCH_GLOBAL_dirs.base_dir, 
+                                                                                  SWITCH_PATH_SEPARATOR, SWITCH_PATH_SEPARATOR, cb->base, date);
+
+               switch_core_session_get_read_impl(session, &read_impl);
+               fh.channels = 0;
+               fh.native_rate = read_impl.actual_samples_per_second;
+                       
+               if (switch_core_file_open(&fh,
+                                                                 file,
+                                                                 0,
+                                                                 read_impl.actual_samples_per_second,
+                                                                 SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file);
+                       switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+                       switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE);
+                       return;
+               }
+
+               switch_mutex_lock(cb->mutex);
+               while ((bytes_read = switch_buffer_read(cb->buffer, pdata, sizeof(pdata)))) {
+                       switch_size_t samples = bytes_read / 2;
+                               
+                       if (switch_core_file_write(&fh, pdata, &samples) != SWITCH_STATUS_SUCCESS) {
+                               break;
+                       }
+               }
+               switch_mutex_unlock(cb->mutex);
+               switch_core_file_close(&fh);
+               switch_core_set_variable("file", file);
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Wrote %s\n", file);
+       }
+
+}
+
+#define SNAP_SYNTAX "start <sec> <read|write>"
+SWITCH_STANDARD_APP(snapshot_app_function)
+{
+       char *argv[4] = { 0 };
+       int argc = 0;
+       char *lbuf = NULL;
+       switch_media_bug_flag_t flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING;
+       if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data))) {
+               argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       } 
+       
+       if (argc < 1) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", SNAP_SYNTAX);
+       }
+
+       if (!strcasecmp(argv[0], "start")) {
+               char *sec = argv[1];
+               char *fl = argv[2];
+               const char *base = argv[3];
+               int seconds = 5;
+
+               if (sec) {
+                       int tmp = atoi(sec);
+                       if (tmp > 5) {
+                               seconds = tmp;
+                       }
+               }
+
+               if (fl) {
+                       flags = SMBF_READ_PING;
+                       if (switch_stristr("read", fl)) {
+                               flags |= SMBF_READ_STREAM;
+                       }
+                       if (switch_stristr("write", fl)) {
+                               flags |= SMBF_WRITE_STREAM;
+                       }
+               }
+
+               if (!base) {
+                       base = "mod_snapshot";
+               }
+
+               start_capture(session, seconds, flags, base);
+               
+       }
+
+       if (!strcasecmp(argv[0], "snap")) {
+               do_snap(session);
+               return;
+       }
+
+}
+
+
+#define SNAP_API_SYNTAX "<uuid> <warning>"
+SWITCH_STANDARD_API(snapshot_function)
+{
+       char *mycmd = NULL, *argv[5] = { 0 };
+       int argc = 0;
+       switch_status_t status = SWITCH_STATUS_FALSE;
+
+       if (!zstr(cmd) && (mycmd = strdup(cmd))) {
+               argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (zstr(cmd) || argc < 1 || zstr(argv[0])) {
+               stream->write_function(stream, "-USAGE: %s\n", SNAP_API_SYNTAX);
+       } else {
+               switch_core_session_t *lsession = NULL;
+
+               if ((lsession = switch_core_session_locate(argv[0]))) {
+                       if (!strcasecmp(argv[1], "snap")) {
+                               do_snap(lsession);
+                       } else if (!strcasecmp(argv[1], "start")) {
+                               char *sec = argv[1];
+                               char *fl = argv[2];
+                               const char *base = argv[3];
+                               int seconds = 5;
+                               switch_media_bug_flag_t flags = SMBF_READ_STREAM | SMBF_WRITE_STREAM | SMBF_READ_PING;
+                               
+                               if (sec) {
+                                       int tmp = atoi(sec);
+                                       if (tmp > 5) {
+                                               seconds = tmp;
+                                       }
+                               }
+
+                               if (fl) {
+                                       flags = SMBF_READ_PING;
+                                       if (switch_stristr("read", fl)) {
+                                               flags |= SMBF_READ_STREAM;
+                                       }
+                                       if (switch_stristr("write", fl)) {
+                                               flags |= SMBF_WRITE_STREAM;
+                                       }
+                               }
+
+                               if (!base) {
+                                       base = "mod_snapshot";
+                               }
+
+                               start_capture(lsession, seconds, flags, base);
+                       }
+
+                       switch_core_session_rwunlock(lsession);
+               }
+       }
+
+       if (status == SWITCH_STATUS_SUCCESS) {
+               stream->write_function(stream, "+OK Success\n");
+       } else {
+               stream->write_function(stream, "-ERR Operation Failed\n");
+       }
+
+       switch_safe_free(mycmd);
+       return SWITCH_STATUS_SUCCESS;
+}
+
+/* Macro expands to: switch_status_t mod_snapshot_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */
+SWITCH_MODULE_LOAD_FUNCTION(mod_snapshot_load)
+{
+       switch_api_interface_t *api_interface;
+       switch_application_interface_t *app_interface;
+
+       /* connect my internal structure to the blank pointer passed to me */
+       *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Hello World!\n");
+       
+       SWITCH_ADD_API(api_interface, "uuid_snapshot", "Snapshot API", snapshot_function, SNAP_API_SYNTAX);
+       SWITCH_ADD_APP(app_interface, "snapshot", "", "", snapshot_app_function, SNAP_SYNTAX, SAF_SUPPORT_NOMEDIA);
+
+       /* indicate that the module should continue to be loaded */
+       return SWITCH_STATUS_SUCCESS;
+}
+
+/* For Emacs:
+ * Local Variables:
+ * mode:c
+ * indent-tabs-mode:t
+ * tab-width:4
+ * c-basic-offset:4
+ * End:
+ * For VIM:
+ * vim:set softtabstop=4 shiftwidth=4 tabstop=4
+ */