]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-7799 Add API command uuid_write_png to mod_png
authorBradley Jokinen <bradleyjokinen@reliancetelephone.com>
Wed, 8 Jul 2015 16:06:15 +0000 (11:06 -0500)
committerBradley Jokinen <bradleyjokinen@reliancetelephone.com>
Wed, 8 Jul 2015 20:36:44 +0000 (15:36 -0500)
This adds the API command uuid_write_png to mod_png which takes a uuid and
file as input. This command takes a screenshot from the session associated
with the given uuid and writes it to the given file. If an absolute path
is not specified, the images directory is used as a prefix.

src/mod/formats/mod_png/mod_png.c

index 01bd93bea5e5e3e45d6669a932fa37f03931ceaa..63936d1aefad6d29174125d14e2dc169d78350e6 100644 (file)
 #pragma warning(disable : 4996)
 #endif
 
+switch_loadable_module_interface_t *MODULE_INTERFACE;
+
 SWITCH_MODULE_LOAD_FUNCTION(mod_png_load);
-SWITCH_MODULE_DEFINITION(mod_png, mod_png_load, NULL, NULL);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_png_shutdown);
+SWITCH_MODULE_DEFINITION(mod_png, mod_png_load, mod_png_shutdown, NULL);
 
 struct png_file_context {
        switch_memory_pool_t *pool;
@@ -201,17 +204,106 @@ static switch_status_t png_file_read_video(switch_file_handle_t *handle, switch_
        return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_bool_t write_png_bug_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);
+       char *path = (char *) user_data;
+
+       switch (type) {
+       case SWITCH_ABC_TYPE_INIT:
+               {
+                       switch_channel_set_flag_recursive(channel, CF_VIDEO_DECODED_READ);
+               }
+               break;
+       case SWITCH_ABC_TYPE_CLOSE:
+               {
+                       switch_thread_rwlock_unlock(MODULE_INTERFACE->rwlock);
+                       switch_channel_clear_flag_recursive(channel, CF_VIDEO_DECODED_READ);
+               }
+               break;
+       case SWITCH_ABC_TYPE_READ_VIDEO_PING:
+               {
+                       switch_frame_t *frame = switch_core_media_bug_get_video_ping_frame(bug);
+                       if (!frame || !frame->img) break;
+                       switch_img_write_png(frame->img, path);
+                       return SWITCH_FALSE;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_TRUE;
+}
+
+SWITCH_STANDARD_API(uuid_write_png_function)
+{
+       int argc = 0;
+       char *argv[2] = { 0 };
+       char *mydata = NULL;
+       char *uuid;
+       char *path;
+       switch_media_bug_t *bug;
+       switch_media_bug_flag_t flags = SMBF_READ_VIDEO_PING;
+       switch_core_session_t *session_;
+
+       if (!zstr(cmd) && (mydata = strdup(cmd))) {
+               argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
+       }
+
+       if (argc < 2) {
+               stream->write_function(stream, "-USAGE: <uuid> <path> \n");     
+               goto end;
+       }
+       
+       uuid = argv[0];
+       if (!(session_ = switch_core_session_locate(uuid))) {
+               stream->write_function(stream, "-ERR Could not locate session.\n");
+               goto end;
+       }
+
+       if (!switch_channel_test_flag(switch_core_session_get_channel(session_), CF_VIDEO)) {
+               stream->write_function(stream, "-ERR Session does not have video.\n");
+               switch_core_session_rwunlock(session_);
+               goto end;
+       }
+
+    if (!switch_is_file_path(argv[1])) {
+        const char *prefix = SWITCH_GLOBAL_dirs.images_dir;
+        path = switch_core_session_sprintf(session_, "%s%s%s", prefix, SWITCH_PATH_SEPARATOR, argv[1]);
+    } else {
+        path = switch_core_session_strdup(session_, argv[1]);
+    }
+
+       switch_thread_rwlock_rdlock(MODULE_INTERFACE->rwlock);
+
+       if (switch_core_media_bug_add(session_, NULL, NULL, write_png_bug_callback, path, 0, flags, &bug) != SWITCH_STATUS_SUCCESS) {
+               stream->write_function(stream, "-ERR Could not attach bug.\n");
+               switch_thread_rwlock_unlock(MODULE_INTERFACE->rwlock);
+       } else {
+               stream->write_function(stream, "+OK\n");
+       }
+
+       switch_core_session_rwunlock(session_);
+
+  end:
+       switch_safe_free(mydata);
+       return SWITCH_STATUS_SUCCESS;
+}
 
 static char *supported_formats[2] = { 0 };
 
 SWITCH_MODULE_LOAD_FUNCTION(mod_png_load)
 {
+       switch_api_interface_t *api_interface;
        switch_file_interface_t *file_interface;
 
        supported_formats[0] = (char *)"png";
 
        /* connect my internal structure to the blank pointer passed to me */
        *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+       MODULE_INTERFACE = *module_interface;
 
        file_interface = (switch_file_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_FILE_INTERFACE);
        file_interface->interface_name = modname;
@@ -221,10 +313,17 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_png_load)
        file_interface->file_read = png_file_read;
        file_interface->file_read_video = png_file_read_video;
 
+       SWITCH_ADD_API(api_interface, "uuid_write_png", "grab an image from a call",uuid_write_png_function, "");
+
        /* indicate that the module should continue to be loaded */
        return SWITCH_STATUS_SUCCESS;
 }
 
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_png_shutdown)
+{
+       return SWITCH_STATUS_UNLOAD;
+}
+
 /* For Emacs:
  * Local Variables:
  * mode:c