<commit_before>/*
 * gabble-media-session.c - Source for GabbleMediaSession
 * Copyright (C) 2006 Collabora Ltd.
 * Copyright (C) 2006 Nokia Corporation
 *   @author <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define DEBUG_FLAG GABBLE_DEBUG_MEDIA

#include "ansi.h"
#include "debug.h"
#include "handles.h"
#include "namespaces.h"
#include "util.h"

#include "telepathy-errors.h"
#include "telepathy-helpers.h"

#include "gabble-connection.h"
#include "gabble-media-channel.h"
#include "gabble-media-stream.h"
#include "gabble-presence-cache.h"
#include "gabble-presence.h"

#include "gabble-media-session.h"
#include "gabble-media-session-signals-marshal.h"
#include "gabble-media-session-glue.h"

G_DEFINE_TYPE(GabbleMediaSession, gabble_media_session, G_TYPE_OBJECT)

#define DEFAULT_SESSION_TIMEOUT 50000

#define GTALK_STREAM_NAME "gtalk"

/* 99 streams gives us a max name length of 8 (videoXX\0 or audioXX\0) */
#define MAX_STREAMS 99
#define MAX_STREAM_NAME_LEN 8

/* signal enum */
enum
{
    NEW_STREAM_HANDLER,
    STREAM_ADDED,
    LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = {0};

/* properties */
enum
{
  PROP_CONNECTION = 1,
  PROP_MEDIA_CHANNEL,
  PROP_OBJECT_PATH,
  PROP_SESSION_ID,
  PROP_INITIATOR,
  PROP_PEER,
  PROP_PEER_RESOURCE,
  PROP_STATE,
  LAST_PROPERTY
};

/* private structure */
typedef struct _GabbleMediaSessionPrivate GabbleMediaSessionPrivate;

struct _GabbleMediaSessionPrivate
{
  GabbleConnection *conn;
  GabbleMediaChannel *channel;
  GabbleMediaSessionMode mode;
  gchar *object_path;

  GHashTable *streams;

  gchar *id;
  JingleInitiator initiator;
  GabbleHandle peer;
  gchar *peer_resource;

  JingleSessionState state;

  gboolean ready;
  gboolean accepted;

  guint timer_id;

  gboolean dispose_has_run;
};

#define GABBLE_MEDIA_SESSION_GET_PRIVATE(obj) \
    ((GabbleMediaSessionPrivate *)obj->priv)

typedef struct {
    gchar *name;
    gchar *attributes;
} SessionStateDescription;

static const SessionStateDescription session_states[] =
{
    { "JS_STATE_PENDING_CREATED",       ANSI_BOLD_ON ANSI_FG_BLACK ANSI_BG_WHITE   },
    { "JS_STATE_PENDING_INITIATE_SENT", ANSI_BOLD_ON               ANSI_BG_CYAN    },
    { "JS_STATE_PENDING_INITIATED",     ANSI_BOLD_ON               ANSI_BG_MAGENTA },
    { "JS_STATE_ACTIVE",                ANSI_BOLD_ON               ANSI_BG_BLUE    },
    { "JS_STATE_ENDED",                                            ANSI_BG_RED     }
};

static void
gabble_media_session_init (GabbleMediaSession *self)
{
  GabbleMediaSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
      GABBLE_TYPE_MEDIA_SESSION, GabbleMediaSessionPrivate);

  self->priv = priv;

  priv->mode = MODE_JINGLE;
  priv->state = JS_STATE_PENDING_CREATED;
  priv->streams = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
      g_object_unref);
}

static void stream_close_cb (GabbleMediaStream *stream,
                             GabbleMediaSession *session);
static void stream_connection_state_changed_cb (GabbleMediaStream *stream,
                                                GParamSpec *param,
                                                GabbleMediaSession *session);
static void stream_got_local_codecs_changed_cb (GabbleMediaStream *stream,
                                                GParamSpec *param,
                                                GabbleMediaSession *session);

static void
_emit_new_stream (const gchar *name,
                  GabbleMediaStream *stream,
                  GabbleMediaSession *session)
{
  gchar *object_path;
  guint id, media_type;

  g_object_get (stream,
                "object-path", &object_path,
                "id", &id,
                "media-type", &media_type,
                NULL);

  /* all of the streams are bidirectional from farsight's point of view, it's
   * just in the signalling they change */
  g_signal_emit (session, signals[NEW_STREAM_HANDLER], 0,
                 object_path, id, media_type,
                 TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);

  g_free (object_path);
}

static GabbleMediaStream *
create_media_stream (GabbleMediaSession *session,
                     const gchar *name,
                     JingleInitiator initiator,
                     guint media_type)
{
  GabbleMediaSessionPrivate *priv;
  gchar *object_path;
  GabbleMediaStream *stream;
  guint id;

  g_assert (GABBLE_IS_MEDIA_SESSION (session));
  g_assert (name != NULL);

  priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);

  /* assert that we only try to make one audio stream in google mode */
  g_assert (priv->mode != MODE_GOOGLE ||
      (media_type == TP_MEDIA_STREAM_TYPE_AUDIO &&
       g_hash_table_size (priv->streams) == 0));
  g_assert (g_hash_table_size (priv->streams) < MAX_STREAMS);

  id = _gabble_media_channel_get_stream_id (priv->channel);

  GMS_DEBUG_INFO (session,
      "creating new %s %s stream called \"%s\" with id %u",
      priv->mode == MODE_GOOGLE ? "google" : "jingle",
      media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video",
      name, id);

  object_path = g_strdup_printf ("%s/IceStream%u", priv->object_path, id);

  stream = g_object_new (GABBLE_TYPE_MEDIA_STREAM,
                         "connection", priv->conn,
                         "media-session", session,
                         "object-path", object_path,
                         "mode", priv->mode,<commit_msg>GabbleMediaSession: name stream objects as MediaStream instead of IceStream<commit_after>/*
 * gabble-media-session.c - Source for GabbleMediaSession
 * Copyright (C) 2006 Collabora Ltd.
 * Copyright (C) 2006 Nokia Corporation
 *   @author <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <dbus/dbus-glib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define DEBUG_FLAG GABBLE_DEBUG_MEDIA

#include "ansi.h"
#include "debug.h"
#include "handles.h"
#include "namespaces.h"
#include "util.h"

#include "telepathy-errors.h"
#include "telepathy-helpers.h"

#include "gabble-connection.h"
#include "gabble-media-channel.h"
#include "gabble-media-stream.h"
#include "gabble-presence-cache.h"
#include "gabble-presence.h"

#include "gabble-media-session.h"
#include "gabble-media-session-signals-marshal.h"
#include "gabble-media-session-glue.h"

G_DEFINE_TYPE(GabbleMediaSession, gabble_media_session, G_TYPE_OBJECT)

#define DEFAULT_SESSION_TIMEOUT 50000

#define GTALK_STREAM_NAME "gtalk"

/* 99 streams gives us a max name length of 8 (videoXX\0 or audioXX\0) */
#define MAX_STREAMS 99
#define MAX_STREAM_NAME_LEN 8

/* signal enum */
enum
{
    NEW_STREAM_HANDLER,
    STREAM_ADDED,
    LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = {0};

/* properties */
enum
{
  PROP_CONNECTION = 1,
  PROP_MEDIA_CHANNEL,
  PROP_OBJECT_PATH,
  PROP_SESSION_ID,
  PROP_INITIATOR,
  PROP_PEER,
  PROP_PEER_RESOURCE,
  PROP_STATE,
  LAST_PROPERTY
};

/* private structure */
typedef struct _GabbleMediaSessionPrivate GabbleMediaSessionPrivate;

struct _GabbleMediaSessionPrivate
{
  GabbleConnection *conn;
  GabbleMediaChannel *channel;
  GabbleMediaSessionMode mode;
  gchar *object_path;

  GHashTable *streams;

  gchar *id;
  JingleInitiator initiator;
  GabbleHandle peer;
  gchar *peer_resource;

  JingleSessionState state;

  gboolean ready;
  gboolean accepted;

  guint timer_id;

  gboolean dispose_has_run;
};

#define GABBLE_MEDIA_SESSION_GET_PRIVATE(obj) \
    ((GabbleMediaSessionPrivate *)obj->priv)

typedef struct {
    gchar *name;
    gchar *attributes;
} SessionStateDescription;

static const SessionStateDescription session_states[] =
{
    { "JS_STATE_PENDING_CREATED",       ANSI_BOLD_ON ANSI_FG_BLACK ANSI_BG_WHITE   },
    { "JS_STATE_PENDING_INITIATE_SENT", ANSI_BOLD_ON               ANSI_BG_CYAN    },
    { "JS_STATE_PENDING_INITIATED",     ANSI_BOLD_ON               ANSI_BG_MAGENTA },
    { "JS_STATE_ACTIVE",                ANSI_BOLD_ON               ANSI_BG_BLUE    },
    { "JS_STATE_ENDED",                                            ANSI_BG_RED     }
};

static void
gabble_media_session_init (GabbleMediaSession *self)
{
  GabbleMediaSessionPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
      GABBLE_TYPE_MEDIA_SESSION, GabbleMediaSessionPrivate);

  self->priv = priv;

  priv->mode = MODE_JINGLE;
  priv->state = JS_STATE_PENDING_CREATED;
  priv->streams = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
      g_object_unref);
}

static void stream_close_cb (GabbleMediaStream *stream,
                             GabbleMediaSession *session);
static void stream_connection_state_changed_cb (GabbleMediaStream *stream,
                                                GParamSpec *param,
                                                GabbleMediaSession *session);
static void stream_got_local_codecs_changed_cb (GabbleMediaStream *stream,
                                                GParamSpec *param,
                                                GabbleMediaSession *session);

static void
_emit_new_stream (const gchar *name,
                  GabbleMediaStream *stream,
                  GabbleMediaSession *session)
{
  gchar *object_path;
  guint id, media_type;

  g_object_get (stream,
                "object-path", &object_path,
                "id", &id,
                "media-type", &media_type,
                NULL);

  /* all of the streams are bidirectional from farsight's point of view, it's
   * just in the signalling they change */
  g_signal_emit (session, signals[NEW_STREAM_HANDLER], 0,
                 object_path, id, media_type,
                 TP_MEDIA_STREAM_DIRECTION_BIDIRECTIONAL);

  g_free (object_path);
}

static GabbleMediaStream *
create_media_stream (GabbleMediaSession *session,
                     const gchar *name,
                     JingleInitiator initiator,
                     guint media_type)
{
  GabbleMediaSessionPrivate *priv;
  gchar *object_path;
  GabbleMediaStream *stream;
  guint id;

  g_assert (GABBLE_IS_MEDIA_SESSION (session));
  g_assert (name != NULL);

  priv = GABBLE_MEDIA_SESSION_GET_PRIVATE (session);

  /* assert that we only try to make one audio stream in google mode */
  g_assert (priv->mode != MODE_GOOGLE ||
      (media_type == TP_MEDIA_STREAM_TYPE_AUDIO &&
       g_hash_table_size (priv->streams) == 0));
  g_assert (g_hash_table_size (priv->streams) < MAX_STREAMS);

  id = _gabble_media_channel_get_stream_id (priv->channel);

  GMS_DEBUG_INFO (session,
      "creating new %s %s stream called \"%s\" with id %u",
      priv->mode == MODE_GOOGLE ? "google" : "jingle",
      media_type == TP_MEDIA_STREAM_TYPE_AUDIO ? "audio" : "video",
      name, id);

  object_path = g_strdup_printf ("%s/MediaStream%u", priv->object_path, id);

  stream = g_object_new (GABBLE_TYPE_MEDIA_STREAM,
                         "connection", priv->conn,
                         "media-session", session,
                         "object-path", object_path,
                         "mode", priv->mode,
{'fraction_non_alphanumeric': 0.08780214502961421, 'fraction_numerical': 0.006082919801504722, 'mean_word_length': 2.9984, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 45, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4708951', 'n_tokens_mistral': 4147, 'n_tokens_neox': 3942, 'n_words': 983}