blob: c10935ea99d44e8810721bd4fba28d502af0e41b [file] [log] [blame]
Stepan Salenikovichc64523b2015-02-27 16:31:00 -05001/*
2 * Copyright (C) 2015 Savoir-Faire Linux Inc.
3 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30
31#include "currentcallview.h"
32
33#include <gtk/gtk.h>
34#include <call.h>
Stepan Salenikovichc64523b2015-02-27 16:31:00 -050035#include <callmodel.h>
Stepan Salenikovich36c025c2015-03-03 19:06:44 -050036#include "utils/drawing.h"
37#include "video/video_widget.h"
Stepan Salenikovich4ac89f12015-03-10 16:48:47 -040038#include <video/previewmanager.h>
Stepan Salenikovich6f687072015-03-26 10:43:37 -040039#include <contactmethod.h>
40#include <person.h>
41#include "delegates/pixbufdelegate.h"
Stepan Salenikovicha448f602015-05-29 13:33:06 -040042#include <media/media.h>
43#include <media/text.h>
44#include <media/textrecording.h>
45#include "models/gtkqtreemodel.h"
Stepan Salenikovichb94873c2015-06-02 16:53:18 -040046#include "video/videowindow.h"
Stepan Salenikovichc64523b2015-02-27 16:31:00 -050047
48struct _CurrentCallView
49{
50 GtkBox parent;
51};
52
53struct _CurrentCallViewClass
54{
55 GtkBoxClass parent_class;
56};
57
58typedef struct _CurrentCallViewPrivate CurrentCallViewPrivate;
59
60struct _CurrentCallViewPrivate
61{
62 GtkWidget *image_peer;
63 GtkWidget *label_identity;
64 GtkWidget *label_status;
65 GtkWidget *label_duration;
Stepan Salenikovich36c025c2015-03-03 19:06:44 -050066 GtkWidget *frame_video;
67 GtkWidget *video_widget;
Stepan Salenikovicha448f602015-05-29 13:33:06 -040068 GtkWidget *revealer_chat;
69 GtkWidget *togglebutton_chat;
70 GtkWidget *textview_chat;
71 GtkWidget *button_chat_input;
72 GtkWidget *entry_chat_input;
73 GtkWidget *scrolledwindow_chat;
Stepan Salenikovichb94873c2015-06-02 16:53:18 -040074 GtkWidget *fullscreen_window;
Stepan Salenikovicha448f602015-05-29 13:33:06 -040075
76 Call *call;
Stepan Salenikovich36c025c2015-03-03 19:06:44 -050077
Stepan Salenikovichc64523b2015-02-27 16:31:00 -050078 QMetaObject::Connection state_change_connection;
79 QMetaObject::Connection call_details_connection;
Stepan Salenikovichc5f08152015-03-19 00:53:23 -040080 QMetaObject::Connection local_renderer_connection;
81 QMetaObject::Connection remote_renderer_connection;
Stepan Salenikovicha448f602015-05-29 13:33:06 -040082 QMetaObject::Connection media_added_connection;
83 QMetaObject::Connection new_message_connection;
Stepan Salenikovich7b60b592015-06-16 12:29:07 -040084 QMetaObject::Connection incoming_msg_connection;
Stepan Salenikovichc64523b2015-02-27 16:31:00 -050085};
86
87G_DEFINE_TYPE_WITH_PRIVATE(CurrentCallView, current_call_view, GTK_TYPE_BOX);
88
89#define CURRENT_CALL_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CURRENT_CALL_VIEW_TYPE, CurrentCallViewPrivate))
90
91static void
92current_call_view_dispose(GObject *object)
93{
94 CurrentCallView *view;
95 CurrentCallViewPrivate *priv;
96
97 view = CURRENT_CALL_VIEW(object);
98 priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
99
100 QObject::disconnect(priv->state_change_connection);
101 QObject::disconnect(priv->call_details_connection);
Stepan Salenikovichc5f08152015-03-19 00:53:23 -0400102 QObject::disconnect(priv->local_renderer_connection);
103 QObject::disconnect(priv->remote_renderer_connection);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400104 QObject::disconnect(priv->media_added_connection);
105 QObject::disconnect(priv->new_message_connection);
Stepan Salenikovich7b60b592015-06-16 12:29:07 -0400106 QObject::disconnect(priv->incoming_msg_connection);
Stepan Salenikovichc5f08152015-03-19 00:53:23 -0400107
Stepan Salenikovichb94873c2015-06-02 16:53:18 -0400108 if (priv->fullscreen_window) {
109 gtk_widget_destroy(priv->fullscreen_window);
110 priv->fullscreen_window = NULL;
111 }
112
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500113 G_OBJECT_CLASS(current_call_view_parent_class)->dispose(object);
114}
115
116static void
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400117chat_toggled(GtkToggleButton *togglebutton, CurrentCallView *self)
118{
119 g_return_if_fail(IS_CURRENT_CALL_VIEW(self));
120 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
121
122 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_chat),
123 gtk_toggle_button_get_active(togglebutton));
124
125 if (gtk_toggle_button_get_active(togglebutton)) {
126 /* create an outgoing media to bring up chat history, if any */
127 priv->call->addOutgoingMedia<Media::Text>();
128 }
129}
130
131static void
132send_chat(G_GNUC_UNUSED GtkWidget *widget, CurrentCallView *self)
133{
134 g_return_if_fail(IS_CURRENT_CALL_VIEW(self));
135 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
136
137 /* make sure there is text to send */
138 const gchar *text = gtk_entry_get_text(GTK_ENTRY(priv->entry_chat_input));
139 if (text && strlen(text) > 0) {
140 priv->call->addOutgoingMedia<Media::Text>()->send(text);
141 /* clear the entry */
142 gtk_entry_set_text(GTK_ENTRY(priv->entry_chat_input), "");
143 }
144}
145
146static void
147scroll_to_bottom(GtkAdjustment *adjustment, G_GNUC_UNUSED gpointer user_data)
148{
149 gtk_adjustment_set_value(adjustment,
150 gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
151}
152
153static void
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500154current_call_view_init(CurrentCallView *view)
155{
156 gtk_widget_init_template(GTK_WIDGET(view));
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400157
158 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
159
160 g_signal_connect(priv->togglebutton_chat, "toggled", G_CALLBACK(chat_toggled), view);
161 g_signal_connect(priv->button_chat_input, "clicked", G_CALLBACK(send_chat), view);
162 g_signal_connect(priv->entry_chat_input, "activate", G_CALLBACK(send_chat), view);
163
164 /* the adjustment params will change only when the model is created and when
165 * new messages are added; in these cases we want to scroll to the bottom of
166 * the chat treeview */
167 GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(priv->scrolledwindow_chat));
168 g_signal_connect(adjustment, "changed", G_CALLBACK(scroll_to_bottom), NULL);
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500169}
170
171static void
172current_call_view_class_init(CurrentCallViewClass *klass)
173{
174 G_OBJECT_CLASS(klass)->dispose = current_call_view_dispose;
175
176 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
177 "/cx/ring/RingGnome/currentcallview.ui");
178
179 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, image_peer);
180 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_identity);
181 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_status);
182 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_duration);
Stepan Salenikovich36c025c2015-03-03 19:06:44 -0500183 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, frame_video);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400184 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, revealer_chat);
185 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, togglebutton_chat);
186 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, textview_chat);
187 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, button_chat_input);
188 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, entry_chat_input);
189 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, scrolledwindow_chat);
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500190}
191
192GtkWidget *
193current_call_view_new(void)
194{
195 return (GtkWidget *)g_object_new(CURRENT_CALL_VIEW_TYPE, NULL);
196}
197
198static void
199update_state(CurrentCallView *view, Call *call)
200{
201 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
202
Stepan Salenikovich7ec8fe82015-06-02 18:26:39 -0400203 gchar *status = g_strdup_printf("%s", call->toHumanStateName().toUtf8().constData());
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500204
Stepan Salenikovich7ec8fe82015-06-02 18:26:39 -0400205 gtk_label_set_text(GTK_LABEL(priv->label_status), status);
206
207 g_free(status);
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500208}
209
210static void
211update_details(CurrentCallView *view, Call *call)
212{
213 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
214
215 /* update call duration */
216 QByteArray ba_length = call->length().toLocal8Bit();
217 gtk_label_set_text(GTK_LABEL(priv->label_duration), ba_length.constData());
218}
219
Stepan Salenikovichc5f08152015-03-19 00:53:23 -0400220static void
Stepan Salenikovichb94873c2015-06-02 16:53:18 -0400221on_fullscreen_destroy(CurrentCallView *view)
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400222{
223 g_return_if_fail(IS_CURRENT_CALL_VIEW(view));
224 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
225
Stepan Salenikovichb94873c2015-06-02 16:53:18 -0400226 /* fullscreen is being destroyed, clear the pointer and un-pause the rendering
227 * in this window */
228 priv->fullscreen_window = NULL;
229 video_widget_pause_rendering(VIDEO_WIDGET(priv->video_widget), FALSE);
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400230}
231
232static gboolean
233on_button_press_in_video_event(GtkWidget *self, GdkEventButton *event, CurrentCallView *view)
234{
235 g_return_val_if_fail(IS_VIDEO_WIDGET(self), FALSE);
236 g_return_val_if_fail(IS_CURRENT_CALL_VIEW(view), FALSE);
237 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
238
239 /* on double click */
240 if (event->type == GDK_2BUTTON_PRESS) {
Stepan Salenikovichb94873c2015-06-02 16:53:18 -0400241 if (priv->fullscreen_window) {
242 /* destroy the fullscreen */
243 gtk_widget_destroy(priv->fullscreen_window);
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400244 } else {
Stepan Salenikovichb94873c2015-06-02 16:53:18 -0400245 /* pause rendering in this window and create fullscreen */
246 video_widget_pause_rendering(VIDEO_WIDGET(priv->video_widget), TRUE);
247
248 priv->fullscreen_window = video_window_new(priv->call,
249 GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(view))));
250
251 /* connect to destruction of fullscreen so we know when to un-pause
252 * the rendering in thiw window */
253 g_signal_connect_swapped(priv->fullscreen_window,
254 "destroy",
255 G_CALLBACK(on_fullscreen_destroy),
256 view);
257
258 /* present the fullscreen widnow */
259 gtk_window_present(GTK_WINDOW(priv->fullscreen_window));
260 gtk_window_fullscreen(GTK_WINDOW(priv->fullscreen_window));
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400261 }
262 }
263
264 /* the event has been fully handled */
265 return TRUE;
266}
267
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400268static void
269print_message_to_buffer(const QModelIndex &idx, GtkTextBuffer *buffer)
270{
271 if (idx.isValid()) {
272 QVariant message = idx.data();
273
274 gchar *text = g_strdup_printf("%s\n", message.value<QString>().toUtf8().constData());
275
276 GtkTextIter iter;
277 gtk_text_buffer_get_end_iter(buffer, &iter);
278 gtk_text_buffer_insert(buffer, &iter, text, -1);
279
280 g_free(text);
281 } else {
282 g_warning("QModelIndex in im model is not valid");
283 }
284}
285
286static void
287parse_chat_model(QAbstractItemModel *model, CurrentCallView *self)
288{
289 g_return_if_fail(IS_CURRENT_CALL_VIEW(self));
290 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
291
292 /* new model, disconnect from the old model updates and clear the text buffer */
293 QObject::disconnect(priv->new_message_connection);
294
295 GtkTextBuffer *new_buffer = gtk_text_buffer_new(NULL);
296 gtk_text_view_set_buffer(GTK_TEXT_VIEW(priv->textview_chat), new_buffer);
297 g_object_unref(new_buffer);
298
299 /* put all the messages in the im model into the text view */
300 for (int row = 0; row < model->rowCount(); ++row) {
301 QModelIndex idx = model->index(row, 0);
302 print_message_to_buffer(idx, new_buffer);
303 }
304
305 /* append new messages */
306 priv->new_message_connection = QObject::connect(
307 model,
308 &QAbstractItemModel::rowsInserted,
309 [priv, model] (const QModelIndex &parent, int first, int last) {
310 for (int row = first; row <= last; ++row) {
311 QModelIndex idx = model->index(row, 0, parent);
312 print_message_to_buffer(idx, gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->textview_chat)));
313 }
314 }
315 );
316}
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400317
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500318void
Stepan Salenikovich7b60b592015-06-16 12:29:07 -0400319monitor_incoming_message(CurrentCallView *self, Media::Text *media)
320{
321 g_return_if_fail(IS_CURRENT_CALL_VIEW(self));
322 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
323
324 /* connect to incoming chat messages to open the chat view */
325 QObject::disconnect(priv->incoming_msg_connection);
326 priv->incoming_msg_connection = QObject::connect(
327 media,
328 &Media::Text::messageReceived,
329 [priv] (G_GNUC_UNUSED const QString& message) {
330 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->togglebutton_chat), TRUE);
331 }
332 );
333}
334
335void
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500336current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) {
337 CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
338
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400339 priv->call = CallModel::instance()->getCall(idx);
Stepan Salenikovich6f687072015-03-26 10:43:37 -0400340
341 /* get call image */
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400342 QVariant var_i = PixbufDelegate::instance()->callPhoto(priv->call, QSize(60, 60), false);
Stepan Salenikovich6f687072015-03-26 10:43:37 -0400343 std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>();
344 gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_peer), image.get());
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500345
346 /* get name */
Stepan Salenikovich9c1f6682015-03-09 16:21:28 -0400347 QVariant var = idx.model()->data(idx, static_cast<int>(Call::Role::Name));
Stepan Salenikovich6f687072015-03-26 10:43:37 -0400348 QByteArray ba_name = var.toString().toUtf8();
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500349 gtk_label_set_text(GTK_LABEL(priv->label_identity), ba_name.constData());
350
351 /* change some things depending on call state */
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400352 update_state(view, priv->call);
353 update_details(view, priv->call);
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500354
355 priv->state_change_connection = QObject::connect(
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400356 priv->call,
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500357 &Call::stateChanged,
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400358 [view, priv]() { update_state(view, priv->call); }
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500359 );
360
361 priv->call_details_connection = QObject::connect(
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400362 priv->call,
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500363 static_cast<void (Call::*)(void)>(&Call::changed),
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400364 [view, priv]() { update_details(view, priv->call); }
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500365 );
Stepan Salenikovich36c025c2015-03-03 19:06:44 -0500366
367 /* video widget */
368 priv->video_widget = video_widget_new();
369 gtk_container_add(GTK_CONTAINER(priv->frame_video), priv->video_widget);
370 gtk_widget_show_all(priv->frame_video);
371
372 /* check if we already have a renderer */
Stepan Salenikovich0f693232015-04-22 10:45:08 -0400373 video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400374 priv->call->videoRenderer(),
Stepan Salenikovich0f693232015-04-22 10:45:08 -0400375 VIDEO_RENDERER_REMOTE);
Stepan Salenikovich36c025c2015-03-03 19:06:44 -0500376
Stepan Salenikovich8e5c9d02015-03-11 14:07:10 -0400377 /* callback for remote renderer */
Stepan Salenikovichc5f08152015-03-19 00:53:23 -0400378 priv->remote_renderer_connection = QObject::connect(
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400379 priv->call,
Stepan Salenikovich9c1f6682015-03-09 16:21:28 -0400380 &Call::videoStarted,
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400381 [priv](Video::Renderer *renderer) {
Stepan Salenikovich0f693232015-04-22 10:45:08 -0400382 video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
383 renderer,
384 VIDEO_RENDERER_REMOTE);
Stepan Salenikovich36c025c2015-03-03 19:06:44 -0500385 }
386 );
Stepan Salenikovich4ac89f12015-03-10 16:48:47 -0400387
Stepan Salenikovich8e5c9d02015-03-11 14:07:10 -0400388 /* local renderer */
Stepan Salenikovich57058802015-03-25 14:16:13 -0400389 if (Video::PreviewManager::instance()->isPreviewing())
Stepan Salenikovich0f693232015-04-22 10:45:08 -0400390 video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
391 Video::PreviewManager::instance()->previewRenderer(),
392 VIDEO_RENDERER_LOCAL);
Stepan Salenikovich8e5c9d02015-03-11 14:07:10 -0400393
394 /* callback for local renderer */
Stepan Salenikovichc5f08152015-03-19 00:53:23 -0400395 priv->local_renderer_connection = QObject::connect(
Stepan Salenikovich8e5c9d02015-03-11 14:07:10 -0400396 Video::PreviewManager::instance(),
397 &Video::PreviewManager::previewStarted,
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400398 [priv](Video::Renderer *renderer) {
Stepan Salenikovich0f693232015-04-22 10:45:08 -0400399 video_widget_push_new_renderer(VIDEO_WIDGET(priv->video_widget),
400 renderer,
401 VIDEO_RENDERER_LOCAL);
Stepan Salenikovich8e5c9d02015-03-11 14:07:10 -0400402 }
403 );
Stepan Salenikovichbfe9ac62015-03-11 12:49:20 -0400404
405 /* catch double click to make full screen */
406 g_signal_connect(priv->video_widget, "button-press-event",
407 G_CALLBACK(on_button_press_in_video_event),
408 view);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400409
410 /* check if text media is already present */
411 if (priv->call->hasMedia(Media::Media::Type::TEXT, Media::Media::Direction::IN)) {
412 Media::Text *text = priv->call->firstMedia<Media::Text>(Media::Media::Direction::IN);
413 parse_chat_model(text->recording()->instantMessagingModel(), view);
Stepan Salenikovich7b60b592015-06-16 12:29:07 -0400414 monitor_incoming_message(view, text);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400415 } else if (priv->call->hasMedia(Media::Media::Type::TEXT, Media::Media::Direction::OUT)) {
416 Media::Text *text = priv->call->firstMedia<Media::Text>(Media::Media::Direction::OUT);
417 parse_chat_model(text->recording()->instantMessagingModel(), view);
Stepan Salenikovich7b60b592015-06-16 12:29:07 -0400418 monitor_incoming_message(view, text);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400419 } else {
420 /* monitor media for messaging text messaging */
421 priv->media_added_connection = QObject::connect(
422 priv->call,
423 &Call::mediaAdded,
424 [view, priv] (Media::Media* media) {
425 if (media->type() == Media::Media::Type::TEXT) {
426 parse_chat_model(((Media::Text*)media)->recording()->instantMessagingModel(), view);
Stepan Salenikovich7b60b592015-06-16 12:29:07 -0400427 monitor_incoming_message(view, (Media::Text*)media);
Stepan Salenikovicha448f602015-05-29 13:33:06 -0400428 QObject::disconnect(priv->media_added_connection);
429 }
430 }
431 );
432 }
Stepan Salenikovichc64523b2015-02-27 16:31:00 -0500433}