]> www.infradead.org Git - pidgin-chime.git/commitdiff
Attempt state management
authorDavid Woodhouse <dwmw@amazon.co.uk>
Sun, 15 Apr 2018 21:20:12 +0000 (23:20 +0200)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Sun, 15 Apr 2018 22:41:45 +0000 (00:41 +0200)
chime/chime-call-screen.c
chime/chime-call-screen.h
chime/chime-call.c
prpl/chat.c

index d310cb104288e74f57547b4a077254b6637415e2..e4db7069ee722b6f529b99fce86cec910daba8e1 100644 (file)
@@ -159,6 +159,7 @@ static void on_screenws_message(SoupWebsocketConnection *ws, gint type,
 
                        gst_app_sink_set_callbacks(screen->screen_sink, &no_appsink_callbacks, NULL, NULL);
                        screen->screen_sink = NULL;
+                       chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_CONNECTED);
                }
                break;
 
@@ -183,7 +184,6 @@ static void screen_ws_connect_cb(GObject *obj, GAsyncResult *res, gpointer _scre
                /* If it was cancelled, 'screen' may have been freed. */
                if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
                        chime_debug("screen ws error %s\n", error->message);
-                       screen->state = CHIME_SCREEN_STATE_FAILED;
                }
                g_clear_error(&error);
                g_object_unref(cxn);
@@ -193,7 +193,13 @@ static void screen_ws_connect_cb(GObject *obj, GAsyncResult *res, gpointer _scre
        g_signal_connect(G_OBJECT(ws), "closed", G_CALLBACK(on_screenws_closed), screen);
        g_signal_connect(G_OBJECT(ws), "message", G_CALLBACK(on_screenws_message), screen);
        screen->ws = ws;
-       screen->state = CHIME_SCREEN_STATE_CONNECTED;
+
+       if (screen->screen_src)
+               chime_call_screen_install_appsrc(screen, screen->screen_src);
+       else if (screen->screen_sink)
+               chime_call_screen_install_appsink(screen, screen->screen_sink);
+       else
+               chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_CONNECTED);
 
        g_object_unref(cxn);
 }
@@ -205,7 +211,6 @@ ChimeCallScreen *chime_call_screen_open(ChimeConnection *cxn, ChimeCall *call)
 
        g_mutex_init(&screen->transport_lock);
 
-       screen->state = CHIME_SCREEN_STATE_CONNECTING;
        screen->call = call;
        screen->cancel = g_cancellable_new();
 
@@ -224,6 +229,8 @@ ChimeCallScreen *chime_call_screen_open(ChimeConnection *cxn, ChimeCall *call)
        gchar *origin = g_strdup_printf("http://%s", soup_uri_get_host(uri));
        soup_uri_free(uri);
 
+       chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_CONNECTING);
+
        chime_connection_websocket_connect_async(g_object_ref(cxn), msg, origin, protocols,
                                                 screen->cancel, screen_ws_connect_cb, screen);
        g_free(origin);
@@ -239,6 +246,8 @@ static void on_final_screenws_close(SoupWebsocketConnection *ws, gpointer _unuse
 
 void chime_call_screen_close(ChimeCallScreen *screen)
 {
+       chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_HANGUP);
+
        if (screen->cancel) {
                g_cancellable_cancel(screen->cancel);
                g_object_unref(screen->cancel);
@@ -277,9 +286,11 @@ static void screen_appsrc_destroy(gpointer _screen)
 {
        ChimeCallScreen *screen = _screen;
 
-       screen_send_packet(screen, SCREEN_PKT_TYPE_VIEWER_END, NULL, 0);
-       screen->screen_src = NULL;
-       screen->state = CHIME_SCREEN_STATE_CONNECTED;
+       if (screen->state == CHIME_SCREEN_STATE_VIEWING) {
+               screen_send_packet(screen, SCREEN_PKT_TYPE_VIEWER_END, NULL, 0);
+               screen->screen_src = NULL;
+               chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_CONNECTED);
+       }
 }
 
 static GstAppSrcCallbacks screen_appsrc_callbacks = {
@@ -290,18 +301,23 @@ static GstAppSrcCallbacks screen_appsrc_callbacks = {
 
 void chime_call_screen_install_appsrc(ChimeCallScreen *screen, GstAppSrc *appsrc)
 {
-       if (screen->screen_sink) {
+       screen->screen_src = appsrc;
+       gst_app_src_set_callbacks(appsrc, &screen_appsrc_callbacks, screen, screen_appsrc_destroy);
+
+       if (screen->state == CHIME_SCREEN_STATE_SENDING)
                screen_send_packet(screen, SCREEN_PKT_TYPE_PRESENTER_END, NULL, 0);
 
+       if (screen->ws) {
+               screen_send_packet(screen, SCREEN_PKT_TYPE_VIEWER_BEGIN, NULL, 0);
+               chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_VIEWING);
+       }
+
+       if (screen->screen_sink) {
                gst_app_sink_set_callbacks(screen->screen_sink, &no_appsink_callbacks, NULL, NULL);
                screen->screen_sink = NULL;
        }
 
-       screen_send_packet(screen, SCREEN_PKT_TYPE_VIEWER_BEGIN, NULL, 0);
 
-       screen->screen_src = appsrc;
-       gst_app_src_set_callbacks(appsrc, &screen_appsrc_callbacks, screen, screen_appsrc_destroy);
-       screen->state = CHIME_SCREEN_STATE_VIEWING;
 }
 
 static GstFlowReturn screen_appsink_new_sample(GstAppSink* self, gpointer data)
@@ -342,23 +358,29 @@ static void screen_appsink_destroy(gpointer _screen)
 {
        ChimeCallScreen *screen = _screen;
 
-       screen_send_packet(screen, SCREEN_PKT_TYPE_PRESENTER_END, NULL, 0);
-       screen->screen_sink = NULL;
-       screen->state = CHIME_SCREEN_STATE_CONNECTED;
+       if (screen->state == CHIME_SCREEN_STATE_SENDING) {
+               screen_send_packet(screen, SCREEN_PKT_TYPE_PRESENTER_END, NULL, 0);
+               screen->screen_sink = NULL;
+               chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_CONNECTED);
+       }
 }
 
 void chime_call_screen_install_appsink(ChimeCallScreen *screen, GstAppSink *appsink)
 {
-       if (screen->screen_src) {
+       screen->screen_sink = appsink;
+       gst_app_sink_set_callbacks(appsink, &screen_appsink_callbacks, screen, screen_appsink_destroy);
+
+       if (screen->state == CHIME_SCREEN_STATE_VIEWING)
                screen_send_packet(screen, SCREEN_PKT_TYPE_VIEWER_END, NULL, 0);
 
+       if (screen->ws) {
+               screen_send_packet(screen, SCREEN_PKT_TYPE_PRESENTER_BEGIN, NULL, 0);
+               chime_call_screen_set_state(screen, CHIME_SCREEN_STATE_SENDING);
+       }
+
+       if (screen->screen_src) {
                gst_app_src_set_callbacks(screen->screen_src, &no_appsrc_callbacks, NULL, NULL);
                screen->screen_src = NULL;
        }
 
-       screen_send_packet(screen, SCREEN_PKT_TYPE_PRESENTER_BEGIN, NULL, 0);
-
-       screen->screen_sink = appsink;
-       gst_app_sink_set_callbacks(appsink, &screen_appsink_callbacks, screen, screen_appsink_destroy);
-       screen->state = CHIME_SCREEN_STATE_SENDING;
 }
index e48cf1018df213fa7e9fad827d6d0493ca93abcc..b18f6658ec0e99f99fb5ebff66f979eca581246e 100644 (file)
@@ -43,6 +43,7 @@ ChimeCallScreen *chime_call_screen_open(ChimeConnection *cxn, ChimeCall *call);
 void chime_call_screen_close(ChimeCallScreen *screen);
 void chime_call_screen_view(ChimeCallScreen *screen);
 void chime_call_screen_unview(ChimeCallScreen *screen);
+void chime_call_screen_set_state(ChimeCallScreen *audio, ChimeScreenState state);
 
 void chime_call_screen_install_appsrc(ChimeCallScreen *screen, GstAppSrc *appsrc);
 void chime_call_screen_install_appsink(ChimeCallScreen *screen, GstAppSink *appsink);
index cec56336c6c5b00e2e81f851a293467733e43cae..fae7bbb26a68d8f7511b21b91bc55db04ecdf5d3 100644 (file)
@@ -56,6 +56,7 @@ static GParamSpec *props[LAST_PROP];
 enum {
        ENDED,
        AUDIO_STATE,
+       SCREEN_STATE,
        PARTICIPANTS_CHANGED,
        NEW_PRESENTER,
        LAST_SIGNAL,
@@ -182,6 +183,11 @@ static void chime_call_class_init(ChimeCallClass *klass)
                              G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST,
                              0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
 
+       signals[SCREEN_STATE] =
+               g_signal_new ("screen-state",
+                             G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST,
+                             0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_INT);
+
        signals[PARTICIPANTS_CHANGED] =
                g_signal_new ("participants-changed",
                              G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST,
@@ -558,7 +564,6 @@ void chime_connection_open_call(ChimeConnection *cxn, ChimeCall *call, gboolean
                chime_jugg_subscribe(cxn, call->channel, "Call", call_jugg_cb, NULL);
                chime_jugg_subscribe(cxn, call->roster_channel, "Roster", call_roster_cb, call);
                call->audio = chime_call_audio_open(cxn, call, muted);
-               call->screen = chime_call_screen_open(cxn, call);
        }
 }
 
@@ -593,6 +598,17 @@ void chime_call_audio_set_state(ChimeCallAudio *audio, ChimeAudioState state)
        g_signal_emit(audio->call, signals[AUDIO_STATE], 0, state);
 }
 
+void chime_call_screen_set_state(ChimeCallScreen *screen, ChimeScreenState state)
+{
+       chime_debug("Screen state %d (was %d)\n", state, screen->state);
+
+       if (screen->state == state)
+               return;
+
+       screen->state = state;
+       g_signal_emit(screen->call, signals[SCREEN_STATE], 0, state);
+}
+
 void chime_call_install_gst_app_callbacks(ChimeCall *call, GstAppSrc *appsrc, GstAppSink *appsink)
 {
        if (call->audio)
index ddba96aebd0ca23441b121021798043d3c29e6ab..f8b767d911f3161a2faa79c6342afb585c11a46a 100644 (file)
@@ -431,6 +431,32 @@ static void on_room_membership(ChimeRoom *room, ChimeRoomMember *member, struct
        }
 }
 
+static void on_screen_state(ChimeCall *call, ChimeScreenState screen_state, struct chime_chat *chat)
+{
+       purple_debug(PURPLE_DEBUG_INFO, "chime", "Screen state %d\n", screen_state);
+
+       if (screen_state == CHIME_SCREEN_STATE_CONNECTING)
+               return;
+
+       if (chat->share_media) {
+               if (screen_state == CHIME_SCREEN_STATE_SENDING) {
+                       purple_media_stream_info(chat->share_media, PURPLE_MEDIA_INFO_ACCEPT, "chime", _("Sharing screen"), FALSE);
+               } else {
+                       purple_debug(PURPLE_DEBUG_INFO, "chime", "Screen presentation ends\n");
+                       purple_media_end(chat->share_media, NULL, NULL);
+                       chat->share_media = NULL;
+               }
+       } else if (chat->screen_media) {
+               if (screen_state == CHIME_SCREEN_STATE_VIEWING) {
+                       purple_media_stream_info(chat->screen_media, PURPLE_MEDIA_INFO_ACCEPT, "chime", chat->screen_title, FALSE);
+               } else {
+                       purple_debug(PURPLE_DEBUG_INFO, "chime", "Screen viewing ends\n");
+                       purple_media_end(chat->screen_media, NULL, NULL);
+                       chat->screen_media = NULL;
+               }
+       }
+}
+
 static void share_media_changed(PurpleMedia *media, PurpleMediaState state, const gchar *id, const gchar *participant, struct chime_chat *chat)
 {
        purple_debug(PURPLE_DEBUG_INFO, "chime", "Share media state %d\n", state);
@@ -446,7 +472,7 @@ static void share_media_changed(PurpleMedia *media, PurpleMediaState state, cons
                }
        }
 }
-
+static void on_call_presenter(ChimeCall *call, ChimeCallParticipant *presenter, struct chime_chat *chat);
 static void share_screen(PurpleBuddy *buddy, gpointer _chat)
 {
        struct chime_chat *chat = _chat;
@@ -454,7 +480,10 @@ static void share_screen(PurpleBuddy *buddy, gpointer _chat)
        if (chat->share_media)
                return;
 
-       const gchar *name = "Sharing screen";
+       /* Stop receiving so we can send */
+       on_call_presenter(chat->call, NULL, chat);
+
+       const gchar *name = _("Sharing screen");
 
        PurpleMediaManager *mgr = purple_media_manager_get();
        chat->share_media = purple_media_manager_create_media(purple_media_manager_get(),
@@ -480,7 +509,7 @@ static void share_screen(PurpleBuddy *buddy, gpointer _chat)
        }
 
        gchar *sinkname = g_strdup_printf("chime_screen_sink_%p", chat->call);
-       gchar *sinkpipe = g_strdup_printf("videorate ! video/x-raw,framerate=3/1 ! videoconvert ! vp8enc ! appsink name=%s async=false", sinkname);
+       gchar *sinkpipe = g_strdup_printf("videorate ! video/x-raw,format=YUY2,framerate=3/1 ! videoconvert ! vp8enc ! appsink name=%s async=false", sinkname);
        PurpleMediaCandidate *cand =
                purple_media_candidate_new(NULL, 1,
                                           PURPLE_MEDIA_CANDIDATE_TYPE_HOST,
@@ -511,7 +540,6 @@ static void share_screen(PurpleBuddy *buddy, gpointer _chat)
        chime_call_send_screen(PURPLE_CHIME_CXN(chat->conv->account->gc), chat->call, GST_APP_SINK(appsink));
        g_object_unref(appsink);
 
-       purple_media_stream_info(chat->share_media, PURPLE_MEDIA_INFO_ACCEPT, "chime", name, FALSE);
        GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(purple_media_manager_get_pipeline(mgr)),
                                  GST_DEBUG_GRAPH_SHOW_ALL, "chime share graph");
 }
@@ -602,13 +630,28 @@ static void screen_ask_cb(gpointer _chat, int choice)
        chime_call_view_screen(PURPLE_CHIME_CXN(chat->conv->account->gc), chat->call, GST_APP_SRC(appsrc));
        g_object_unref(appsrc);
 
-       purple_media_stream_info(chat->screen_media, PURPLE_MEDIA_INFO_ACCEPT, "chime", name, FALSE);
        GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(purple_media_manager_get_pipeline(mgr)),
                                  GST_DEBUG_GRAPH_SHOW_ALL, "chime screen graph");
 }
 
+static void view_screen(PurpleBuddy *buddy, gpointer _chat)
+{
+       struct chime_chat *chat = _chat;
+
+       if (chat->screen_ask_ui) {
+               purple_request_close(PURPLE_REQUEST_ACTION, chat->screen_ask_ui);
+               chat->screen_ask_ui = NULL;
+       }
+       screen_ask_cb(chat, 0);
+}
+
 static void on_call_presenter(ChimeCall *call, ChimeCallParticipant *presenter, struct chime_chat *chat)
 {
+       /* If we are the sender, don't offer to receive... */
+       if (chat->share_media && presenter &&
+           !g_strcmp0(presenter->participant_id, chime_connection_get_profile_id(PURPLE_CHIME_CXN(chat->conv->account->gc))))
+               presenter = NULL;
+
        if (!presenter || g_strcmp0(chat->presenter_id, presenter->participant_id)) {
                if (chat->screen_ask_ui) {
                        purple_request_close(PURPLE_REQUEST_ACTION, chat->screen_ask_ui);
@@ -632,7 +675,7 @@ static void on_call_presenter(ChimeCall *call, ChimeCallParticipant *presenter,
 
                gchar *primary = g_strdup_printf(_("%s is now sharing a screen."), presenter->full_name);
                chat->screen_ask_ui = purple_request_action(chat, _("Screenshare available"), primary,
-                                                           chat->conv->account->username, 1,
+                                                           chime_call_get_alert_body(chat->call), 1,
                                                            chat->conv->account, presenter->email, chat->conv,
                                                            chat, 2,
                                                            _("Ignore"), screen_ask_cb,
@@ -681,7 +724,7 @@ void chime_destroy_chat(struct chime_chat *chat)
                        PurpleMedia *media = chat->share_media;
                        chat->share_media = NULL;
 
-                       purple_media_end(media, "chime", "Sharing screen");
+                       purple_media_end(media, "chime", _("Sharing screen"));
                        purple_media_manager_remove_media(purple_media_manager_get(), media);
                }
 
@@ -752,6 +795,7 @@ struct chime_chat *do_join_chat(PurpleConnection *conn, ChimeConnection *cxn, Ch
                chat->meeting = g_object_ref(meeting);
                chat->call = chime_meeting_get_call(meeting);
                if (chat->call) {
+                       g_signal_connect(chat->call, "screen-state", G_CALLBACK(on_screen_state), chat);
                        g_signal_connect(chat->call, "audio-state", G_CALLBACK(on_audio_state), chat);
                        g_signal_connect(chat->call, "participants-changed", G_CALLBACK(on_call_participants), chat);
                        g_signal_connect(chat->call, "new-presenter", G_CALLBACK(on_call_presenter), chat);
@@ -1065,6 +1109,10 @@ GList *chime_purple_chat_menu(PurpleChat *pchat)
                items = g_list_append(items,
                                      purple_menu_action_new(_("Join audio call"),
                                                             PURPLE_CALLBACK(join_audio), chat, NULL));
+               if (chat->screen_title)
+                       items = g_list_append(items,
+                                             purple_menu_action_new(chat->screen_title,
+                                                                    PURPLE_CALLBACK(view_screen), chat, NULL));
                items = g_list_append(items,
                                      purple_menu_action_new(_("Share screen (well, camera)"),
                                                             PURPLE_CALLBACK(share_screen), chat, NULL));