static void got_snapshot(AvatarManipulation *self) { AvatarManipulationPrivate *priv = AVATAR_MANIPULATION_GET_PRIVATE(self); GdkPixbuf* pix = video_widget_get_snapshot(VIDEO_WIDGET(priv->video_widget)); if (priv->crop_area) gtk_container_remove(GTK_CONTAINER(priv->vbox_crop_area), priv->crop_area); priv->crop_area = cc_crop_area_new(); gtk_widget_show(priv->crop_area); gtk_box_pack_start(GTK_BOX(priv->vbox_crop_area), priv->crop_area, TRUE, TRUE, 0); cc_crop_area_set_picture(CC_CROP_AREA(priv->crop_area), pix); set_state(self, AVATAR_MANIPULATION_STATE_EDIT); }
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 take_a_photo(AvatarManipulation *self) { AvatarManipulationPrivate *priv = AVATAR_MANIPULATION_GET_PRIVATE(self); video_widget_take_snapshot(VIDEO_WIDGET(priv->video_widget)); }
void current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) { CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view); priv->call = CallModel::instance().getCall(idx); /* get call image */ QVariant var_i = GlobalInstances::pixmapManipulator().callPhoto(priv->call, QSize(60, 60), false); std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>(); gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_peer), image.get()); /* get name */ QVariant var = idx.model()->data(idx, static_cast<int>(Call::Role::Name)); QByteArray ba_name = var.toString().toUtf8(); gtk_label_set_text(GTK_LABEL(priv->label_identity), ba_name.constData()); /* change some things depending on call state */ update_state(view, priv->call); update_details(view, priv->call); priv->state_change_connection = QObject::connect( priv->call, &Call::stateChanged, [view, priv]() { update_state(view, priv->call); } ); priv->call_details_connection = QObject::connect( priv->call, static_cast<void (Call::*)(void)>(&Call::changed), [view, priv]() { update_details(view, priv->call); } ); /* check if we already have a renderer */ video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget), priv->call->videoRenderer(), VIDEO_RENDERER_REMOTE); /* callback for remote renderer */ priv->remote_renderer_connection = QObject::connect( priv->call, &Call::videoStarted, [priv](Video::Renderer *renderer) { video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget), renderer, VIDEO_RENDERER_REMOTE); } ); /* local renderer */ if (Video::PreviewManager::instance().isPreviewing()) video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget), Video::PreviewManager::instance().previewRenderer(), VIDEO_RENDERER_LOCAL); /* callback for local renderer */ priv->local_renderer_connection = QObject::connect( &Video::PreviewManager::instance(), &Video::PreviewManager::previewStarted, [priv](Video::Renderer *renderer) { video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget), renderer, VIDEO_RENDERER_LOCAL); } ); /* handle video widget button click event */ g_signal_connect(priv->video_widget, "button-press-event", G_CALLBACK(video_widget_on_button_press_in_screen_event), priv->call); /* handle video widget drag and drop*/ g_signal_connect(priv->video_widget, "drag-data-received", G_CALLBACK(video_widget_on_drag_data_received), priv->call); /* catch double click to make full screen */ g_signal_connect(priv->video_widget, "button-press-event", G_CALLBACK(on_button_press_in_video_event), view); /* check if auto quality is enabled or not; */ if (const auto& codecModel = priv->call->account()->codecModel()) { const auto& videoCodecs = codecModel->videoCodecs(); if (videoCodecs->rowCount() > 0) { /* we only need to check the first codec since by default it is ON for all, and the * gnome client sets its ON or OFF for all codecs as well */ const auto& idx = videoCodecs->index(0,0); auto auto_quality_enabled = idx.data(static_cast<int>(CodecModel::Role::AUTO_QUALITY_ENABLED)).toString() == "true"; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_autoquality), auto_quality_enabled); // TODO: save the manual quality setting in the client and set the slider to that value here; // the daemon resets the bitrate/quality between each call, and the default may be // different for each codec, so there is no reason to check it here } } /* init chat view */ auto chat_view = chat_view_new_call(priv->call); gtk_container_add(GTK_CONTAINER(priv->frame_chat), chat_view); /* check if there were any chat notifications and open the chat view if so */ if (ring_notify_close_chat_notification(priv->call->peerContactMethod())) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->togglebutton_chat), TRUE); /* show chat view on any new incoming messages */ g_signal_connect_swapped(chat_view, "new-messages-displayed", G_CALLBACK(show_chat_view), view); }