static void set_state(AvatarManipulation *self, AvatarManipulationState state) { // note: this funciton does not check if the state transition is valid, this is assumed to have // been done by the caller AvatarManipulationPrivate *priv = AVATAR_MANIPULATION_GET_PRIVATE(self); // save prev state priv->last_state = priv->state; switch (state) { case AVATAR_MANIPULATION_STATE_CURRENT: { /* get the current or default profile avatar */ auto photo = GlobalInstances::pixmapManipulator().contactPhoto( ProfileModel::instance().selectedProfile()->person(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT), false); std::shared_ptr<GdkPixbuf> pixbuf_photo = photo.value<std::shared_ptr<GdkPixbuf>>(); if (photo.isValid()) { gtk_image_set_from_pixbuf (GTK_IMAGE(priv->image_avatar), pixbuf_photo.get()); } else { g_warning("invlid pixbuf"); } gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_views), "page_avatar"); /* available actions: start camera (if available) or choose image */ if (Video::DeviceModel::instance().rowCount() > 0) { // TODO: update if a video device gets inserted while in this state gtk_widget_set_visible(priv->button_start_camera, true); } gtk_widget_set_visible(priv->button_box_current, true); gtk_widget_set_visible(priv->button_box_photo, false); gtk_widget_set_visible(priv->button_box_edit, false); /* make sure video widget and camera is not running */ if (priv->video_started_by_avatar_manipulation) Video::PreviewManager::instance().stopPreview(); if (priv->video_widget) { gtk_container_remove(GTK_CONTAINER(priv->frame_video), priv->video_widget); priv->video_widget = NULL; } } break; case AVATAR_MANIPULATION_STATE_PHOTO: { // start the video; if its not available we should not be in this state priv->video_widget = video_widget_new(); g_signal_connect_swapped(priv->video_widget, "snapshot-taken", G_CALLBACK (got_snapshot), self); gtk_widget_set_vexpand_set(priv->video_widget, FALSE); gtk_widget_set_hexpand_set(priv->video_widget, FALSE); gtk_container_add(GTK_CONTAINER(priv->frame_video), priv->video_widget); gtk_widget_set_visible(priv->video_widget, true); gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_views), "page_photobooth"); /* local renderer, but set as "remote" so that it takes up the whole screen */ video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget), Video::PreviewManager::instance().previewRenderer(), VIDEO_RENDERER_REMOTE); if (!Video::PreviewManager::instance().isPreviewing()) { priv->video_started_by_avatar_manipulation = TRUE; Video::PreviewManager::instance().startPreview(); } else { priv->video_started_by_avatar_manipulation = FALSE; } /* available actions: take snapshot, return*/ gtk_widget_set_visible(priv->button_box_current, false); gtk_widget_set_visible(priv->button_box_photo, true); gtk_widget_set_visible(priv->button_box_edit, false); } break; case AVATAR_MANIPULATION_STATE_EDIT: { /* make sure video widget and camera is not running */ if (priv->video_started_by_avatar_manipulation) Video::PreviewManager::instance().stopPreview(); if (priv->video_widget) { gtk_container_remove(GTK_CONTAINER(priv->frame_video), priv->video_widget); priv->video_widget = NULL; } /* available actions: set avatar, return */ gtk_widget_set_visible(priv->button_box_current, false); gtk_widget_set_visible(priv->button_box_photo, false); gtk_widget_set_visible(priv->button_box_edit, true); gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_views), "page_edit_view"); } break; } priv->state = state; }
static void current_call_view_init(CurrentCallView *view) { gtk_widget_init_template(GTK_WIDGET(view)); CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view); /* create video widget and overlay the call info and controls on it */ priv->video_widget = video_widget_new(); gtk_container_add(GTK_CONTAINER(priv->frame_video), priv->video_widget); gtk_widget_show_all(priv->frame_video); auto stage = gtk_clutter_embed_get_stage(GTK_CLUTTER_EMBED(priv->video_widget)); auto actor_info = gtk_clutter_actor_new_with_contents(priv->hbox_call_info); auto actor_controls = gtk_clutter_actor_new_with_contents(priv->hbox_call_controls); clutter_actor_add_child(stage, actor_info); clutter_actor_set_x_align(actor_info, CLUTTER_ACTOR_ALIGN_FILL); clutter_actor_set_y_align(actor_info, CLUTTER_ACTOR_ALIGN_START); clutter_actor_add_child(stage, actor_controls); clutter_actor_set_x_align(actor_controls, CLUTTER_ACTOR_ALIGN_CENTER); clutter_actor_set_y_align(actor_controls, CLUTTER_ACTOR_ALIGN_END); /* add fade in and out states to the info and controls */ priv->time_last_mouse_motion = g_get_monotonic_time(); priv->fade_info = create_fade_out_transition(); priv->fade_controls = create_fade_out_transition(); clutter_actor_add_transition(actor_info, "fade_info", priv->fade_info); clutter_actor_add_transition(actor_controls, "fade_controls", priv->fade_controls); clutter_timeline_set_direction(CLUTTER_TIMELINE(priv->fade_info), CLUTTER_TIMELINE_BACKWARD); clutter_timeline_set_direction(CLUTTER_TIMELINE(priv->fade_controls), CLUTTER_TIMELINE_BACKWARD); clutter_timeline_stop(CLUTTER_TIMELINE(priv->fade_info)); clutter_timeline_stop(CLUTTER_TIMELINE(priv->fade_controls)); /* have a timer check every 1 second if the controls should fade out */ priv->timer_fade = g_timeout_add(1000, (GSourceFunc)timeout_check_last_motion_event, view); /* connect to the mouse motion event to reset the last moved time */ g_signal_connect_swapped(priv->video_widget, "motion-notify-event", G_CALLBACK(mouse_moved), view); g_signal_connect_swapped(priv->video_widget, "button-press-event", G_CALLBACK(mouse_moved), view); g_signal_connect_swapped(priv->video_widget, "button-release-event", G_CALLBACK(mouse_moved), view); /* manually handle the focus of the video widget to be able to focus on the call controls */ g_signal_connect(priv->video_widget, "focus", G_CALLBACK(video_widget_focus), view); /* toggle whether or not the chat is displayed */ g_signal_connect(priv->togglebutton_chat, "toggled", G_CALLBACK(chat_toggled), view); /* bind the chat orientation to the gsetting */ priv->settings = g_settings_new_full(get_ring_schema(), NULL, NULL); g_settings_bind_with_mapping(priv->settings, "chat-pane-horizontal", priv->paned_call, "orientation", G_SETTINGS_BIND_GET, map_boolean_to_orientation, nullptr, nullptr, nullptr); g_signal_connect(priv->scalebutton_quality, "value-changed", G_CALLBACK(quality_changed), view); /* customize the quality button scale */ if (auto scale_box = gtk_scale_button_get_box(GTK_SCALE_BUTTON(priv->scalebutton_quality))) { priv->checkbutton_autoquality = gtk_check_button_new_with_label(C_("Enable automatic video quality", "Auto")); gtk_widget_show(priv->checkbutton_autoquality); gtk_box_pack_start(GTK_BOX(scale_box), priv->checkbutton_autoquality, FALSE, TRUE, 0); g_signal_connect(priv->checkbutton_autoquality, "toggled", G_CALLBACK(autoquality_toggled), view); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_autoquality), TRUE); } if (auto scale = gtk_scale_button_get_scale(GTK_SCALE_BUTTON(priv->scalebutton_quality))) { g_signal_connect(scale, "button-press-event", G_CALLBACK(quality_button_pressed), view); g_signal_connect(scale, "button-release-event", G_CALLBACK(quality_button_released), view); } }