Ejemplo n.º 1
0
static JsonGenerator *
_model_to_generator (MexQueueModel *model)
{
  gint i;
  JsonArray *json_array;
  JsonNode *root;
  JsonGenerator *generator;

  json_array = json_array_sized_new (mex_model_get_length (MEX_MODEL (model)));

  for (i = 0; i < mex_model_get_length (MEX_MODEL (model)); i++)
    {
      MexContent *content;
      JsonNode *content_node;

      content = mex_model_get_content (MEX_MODEL (model), i);

      content_node = json_gobject_serialize (G_OBJECT (content));
      json_array_add_element (json_array, content_node);
    }

  generator = json_generator_new ();
  root = json_node_new (JSON_NODE_ARRAY);
  json_node_set_array (root, json_array);

  json_generator_set_root (generator, root);

  json_array_unref (json_array);
  json_node_free (root);

  return generator;
}
Ejemplo n.º 2
0
/**
  * mex_media_controls_get_enqueued:
  * @controls: The MexMediaControls widget
  * @current_content: MexContent that the player is currently playing
  *
  * If the media controls has been given a queue model then return the next
  * MexContent in the queue model.
  *
  * Return value: The next content in the queue or NULL
  */
MexContent *
mex_media_controls_get_enqueued (MexMediaControls *controls,
                                 MexContent *current_content)
{
    MexMediaControlsPrivate *priv;
    MexModel *queue;
    MexContent *content = NULL;

    if (!MEX_IS_MEDIA_CONTROLS (controls) || !MEX_IS_CONTENT (current_content))
        return NULL;

    priv = controls->priv;

    if (priv->is_queue_model == FALSE)
        return NULL;

    queue = mex_proxy_get_model (priv->proxy);
    if (queue)
    {
        gint idx, length;

        idx = mex_model_index (queue, current_content);
        length = mex_model_get_length (queue);

        if (idx++ > length)
            return NULL;

        content = mex_model_get_content (queue, idx);
    }

    return content;
}
Ejemplo n.º 3
0
static void
_add_remove_recursive (MexModel *queue_model, MexModel *model, gboolean add)
{
  gint len, i;

  len = mex_model_get_length (model);

  for (i=0; i < len; i++)
    {
      MexContent *content;
      const gchar *mimetype;

      content = mex_model_get_content (model, i);

      mimetype = mex_content_get_metadata (content,
                                           MEX_CONTENT_METADATA_MIMETYPE);

      /* Don't accidentally add a directory or group to the queue */
      if (!g_strcmp0 (mimetype, "x-grl/box")
          || !g_strcmp0 (mimetype, "x-mex/group"))
        continue;

      if (add)
        mex_model_add_content (queue_model, content);
      else
        mex_model_remove_content (queue_model, content);
    }
  g_object_unref (model);
}
Ejemplo n.º 4
0
static void
mex_aggregate_model_clear_model (MexAggregateModel *self,
                                 MexModel          *model)
{
    gint i;
    GList *c, *remove;
    MexContent *content;

    MexAggregateModelPrivate *priv = self->priv;

    i = 0;
    remove = NULL;
    while ((content = mex_model_get_content (MEX_MODEL (self), i++)))
    {
        MexModel *parent = g_hash_table_lookup (priv->content_to_model, content);

        if (parent == model)
        {
            g_hash_table_remove (priv->content_to_model, content);
            remove = g_list_prepend (remove, content);
        }
    }

    /* Remove the contents after the loop, to avoid modifying what we're
     * iterating over.
     */
    for (c = remove; c; c = c->next)
        mex_model_remove_content (MEX_MODEL (self), MEX_CONTENT (c->data));

    g_list_free (remove);
}
Ejemplo n.º 5
0
static void
mex_view_model_set_model (MexViewModel *self,
                          MexModel     *model)
{
  MexViewModelPrivate *priv = self->priv;

  if (model == priv->model)
    return;

  if (model)
    {
      MexContent *content;
      GController *controller;
      gint i = 0;

      priv->model = g_object_ref_sink (model);

      controller = mex_model_get_controller (model);
      g_signal_connect (controller, "changed",
                        G_CALLBACK (mex_view_model_controller_changed_cb),
                        self);

      /* copy initial items across */
      g_ptr_array_set_size (priv->internal_items,
                            mex_model_get_length (priv->model));

      while ((content = mex_model_get_content (priv->model, i)))
        priv->internal_items->pdata[i++] = content;
    }

  mex_view_model_refresh_external_items (self);
}
Ejemplo n.º 6
0
/**
 * mex_column_populate:
 *
 * Add an item to the column for each item in the current model
 */
static void
mex_column_populate (MexColumn *column)
{
  MexContent *content;
  gint i = 0;

  g_return_if_fail (column->priv->model != NULL);

  while ((content = mex_model_get_content (column->priv->model, i)))
    mex_column_add_content (column, content, i++);
}
Ejemplo n.º 7
0
static void
mex_search_plugin_model_changed_cb (GController          *controller,
                                    GControllerAction     action,
                                    GControllerReference *ref,
                                    MexModel             *model)
{
  gint i;
  gint n_indices = g_controller_reference_get_n_indices (ref);

  /* If the MIME type is unset, set one so that it's still playable in the
   * main UI. This plugin will only use white-listed Grilo plugins that we
   * know return playable media, so this is OK.
   */
  switch (action)
    {
    case G_CONTROLLER_ADD:
      for (i = 0; i < n_indices; i++)
        {
          gchar *notify;
          MexContent *content;
          const gchar *property_name;

          gint content_index = g_controller_reference_get_index_uint (ref, i);
          content = mex_model_get_content (model, content_index);

          /* Make sure the mime-type remains useful */
          property_name =
            mex_content_get_property_name (content,
                                           MEX_CONTENT_METADATA_MIMETYPE);
          if (property_name)
            {
              notify = g_strconcat ("notify::", property_name, NULL);
              g_signal_connect (content, notify,
                                G_CALLBACK (mex_search_plugin_mimetype_set_cb),
                                NULL);
              g_free (notify);
            }

          mex_search_plugin_mimetype_set_cb (content);
        }
      break;

    default:
      break;
    }
}
Ejemplo n.º 8
0
void
mex_aggregate_model_add_model (MexAggregateModel *aggregate,
                               MexModel          *model)
{
    gint i;
    MexContent *content;
    GController *controller;
    MexAggregateModelPrivate *priv;

    g_return_if_fail (MEX_IS_AGGREGATE_MODEL (aggregate));
    g_return_if_fail (MEX_IS_MODEL (model));

    priv = aggregate->priv;
    if (g_list_find (priv->models, model))
        return;

    /* Add a link back to the model from the controller */
    controller = mex_model_get_controller (model);
    g_hash_table_insert (priv->controller_to_model, controller, model);

    /* Add model to list */
    priv->models = g_list_insert_sorted (priv->models, model,
                                         (GCompareFunc) mex_aggregate_model_sort_func);

    /* Add existing items */
    i = 0;
    while ((content = mex_model_get_content (model, i)))
    {
        g_hash_table_insert (priv->content_to_model, content, model);
        mex_model_add_content (MEX_MODEL (aggregate), content);
        i++;
    }

    /* Connect to the controller changed signal */
    g_signal_connect (controller, "changed",
                      G_CALLBACK (mex_aggregate_model_controller_changed_cb),
                      aggregate);

    /* Emit added signal */
    g_signal_emit (aggregate, signals[MODEL_ADDED], 0, model);
}
Ejemplo n.º 9
0
static void
mex_music_player_set_context (MexContentView *player,
                              MexModel       *model)
{
  MexMusicPlayerPrivate *priv = MEX_MUSIC_PLAYER (player)->priv;
  ClutterActor *box, *button;
  MexContent *content;
  gint i;

  if (priv->model)
    g_object_unref (priv->model);

  priv->model = model;

  if (model)
    g_object_ref (model);

  box = mex_script_get_actor (priv->script, "tracks");
  clutter_actor_remove_all_children (box);

  for (i = 0; (content = mex_model_get_content (model, i)); i++)
    {
      const gchar *title;

      title = mex_content_get_metadata (content, MEX_CONTENT_METADATA_TITLE);
      button = mx_button_new_with_label (title);
      mx_stylable_set_style_class (MX_STYLABLE (button), "Track");
      mx_button_set_is_toggle (MX_BUTTON (button), TRUE);
      g_object_set_data (G_OBJECT (button), "content", content);
      g_signal_connect (button, "clicked",
                        G_CALLBACK (mex_music_player_item_clicked), player);

      mx_button_set_icon_position (MX_BUTTON (button), MX_POSITION_RIGHT);

      clutter_actor_add_child (box, button);
    }
}
Ejemplo n.º 10
0
static void
mex_music_player_update_index (MexMusicPlayer *player,
                               gint            new_index)
{
  MexMusicPlayerPrivate *priv = player->priv;
  gint content_index, length;
  MexContent *new_content;

  length = mex_model_get_length (priv->model);

  if (priv->repeat)
    {
      if (new_index >= length)
        new_index = 0;
      else if (new_index < 0)
        new_index = length - 1;
    }
  else
    {
      if (new_index >= length)
        new_index = length - 1;
      else if (new_index < 0)
        new_index = 0;
    }

  priv->current_index = new_index;

  if (priv->shuffle)
    content_index = g_array_index (priv->shuffle, gint, priv->current_index);
  else
    content_index = priv->current_index;

  new_content = mex_model_get_content (priv->model, content_index);

  mex_music_player_set_content (MEX_CONTENT_VIEW (player), new_content);
}
Ejemplo n.º 11
0
/**
 * mex_column_controller_changed:
 *
 * Callback for when the current model controller's "changed" signal is emitted
 */
static void
mex_column_controller_changed (GController          *controller,
                               GControllerAction     action,
                               GControllerReference *ref,
                               MexColumn            *column)
{
  MexColumnPrivate *priv = column->priv;
  gint i, n_indices;
  MexContent *content;

  n_indices = g_controller_reference_get_n_indices (ref);

  switch (action)
    {
    case G_CONTROLLER_ADD:
      for (i = 0; i < n_indices; i++)
        {
          gint content_index = g_controller_reference_get_index_uint (ref, i);
          content = mex_model_get_content (priv->model, content_index);

          mex_column_add_content (column, content, content_index);
        }
      break;

    case G_CONTROLLER_REMOVE:
      for (i = 0; i < n_indices; i++)
        {
          GList *lnk;

          gint content_index = g_controller_reference_get_index_uint (ref, i);

          lnk = g_list_nth (priv->children, content_index);

          if (lnk->data == priv->current_focus)
            priv->current_focus = NULL;

          clutter_actor_destroy (lnk->data);
          priv->children = g_list_delete_link (priv->children, lnk);
        }
      break;

    case G_CONTROLLER_UPDATE:
      break;

    case G_CONTROLLER_CLEAR:
      mex_column_clear (column);
      break;

    case G_CONTROLLER_REPLACE:
      mex_column_clear (column);
      mex_column_populate (column);
      break;

    case G_CONTROLLER_INVALID_ACTION:
      g_warning (G_STRLOC ": Controller has issued an error");
      break;

    default:
      g_warning (G_STRLOC ": Unhandled action");
      break;
    }

  clutter_actor_queue_relayout (CLUTTER_ACTOR (column));
}
Ejemplo n.º 12
0
static void
_controller_changed_cb (GController          *controller,
                        GControllerAction     action,
                        GControllerReference *ref,
                        MexQueueModel        *model)
{
  MexQueueModelPrivate *priv = model->priv;
  guint index_;
  MexContent *content;

  /*
   * MexGenericContent only does single items at a time so we have an
   * assumption here that our reference only contains a single item
   */

  if (action == G_CONTROLLER_ADD || action == G_CONTROLLER_REMOVE)
    {
      index_ = g_controller_reference_get_index_uint (ref, 0);
      content = mex_model_get_content (MEX_MODEL (model), index_);
    }

  if (action == G_CONTROLLER_ADD)
    {
      mex_content_set_metadata (content,
                                MEX_CONTENT_METADATA_QUEUED,
                                "yes");
    }
  else if (action == G_CONTROLLER_REMOVE)
    {
      mex_content_set_metadata (content,
                                MEX_CONTENT_METADATA_QUEUED,
                                NULL);
    }
  else if (action == G_CONTROLLER_CLEAR)
    {
      gint model_length;
      model_length = mex_model_get_length (MEX_MODEL (model));

      for (index_=0; index_ < model_length; index_++)
        {
          content = mex_model_get_content (MEX_MODEL (model), index_);

          mex_content_set_metadata (content,
                                    MEX_CONTENT_METADATA_QUEUED,
                                    NULL);
        }
    }
  else
    {
      GEnumClass *enum_class;

      enum_class = g_type_class_ref (G_TYPE_CONTROLLER_ACTION);

      g_critical (G_STRLOC ": Unexpected GController action: %s",
                  (g_enum_get_value (enum_class,
                                     action))->value_name);

      g_type_class_unref (enum_class);
    }

  if (priv->serialise_idle_id)
    return;

  /* Need to use a high priority idle here since we want to try and write
   * *after* the content has been removed from the model
   */
  priv->serialise_idle_id = g_idle_add_full (G_PRIORITY_DEFAULT,
                                             (GSourceFunc)_serialise_idle_cb,
                                             g_object_ref (model),
                                             g_object_unref);
}
Ejemplo n.º 13
0
static void
mex_aggregate_model_controller_changed_cb (GController          *controller,
        GControllerAction     action,
        GControllerReference *ref,
        MexAggregateModel    *self)
{
    gint i;

    gint n_indices = 0;
    MexAggregateModelPrivate *priv = self->priv;
    MexModel *model = g_hash_table_lookup (priv->controller_to_model, controller);

    if (!model)
    {
        g_warning (G_STRLOC ": Signal from unknown controller");
        return;
    }

    if (ref)
        n_indices = g_controller_reference_get_n_indices (ref);

    switch (action)
    {
    case G_CONTROLLER_ADD:
        for (i = 0; i < n_indices; i++)
        {
            MexContent *content;

            gint content_index = g_controller_reference_get_index_uint (ref, i);
            content = mex_model_get_content (model, content_index);
            g_hash_table_insert (priv->content_to_model, content, model);

            mex_model_add_content (MEX_MODEL (self), content);
        }
        break;

    case G_CONTROLLER_REMOVE:
        for (i = 0; i < n_indices; i++)
        {
            MexContent *content;

            gint content_index = g_controller_reference_get_index_uint (ref, i);

            content = mex_model_get_content (model, content_index);
            g_hash_table_remove (priv->content_to_model, content);

            mex_model_remove_content (MEX_MODEL (self), content);
        }
        break;

    case G_CONTROLLER_UPDATE:
        break;

    case G_CONTROLLER_CLEAR:
        mex_aggregate_model_clear_model (self, model);
        break;

    case G_CONTROLLER_REPLACE:
    {
        MexContent *content;

        mex_aggregate_model_clear_model (self, model);
        i = 0;
        while ((content = mex_model_get_content (model, i++)))
        {
            g_hash_table_insert (priv->content_to_model, content, model);
            mex_model_add_content (MEX_MODEL (self), content);
        }
    }
    break;

    case G_CONTROLLER_INVALID_ACTION:
        g_warning (G_STRLOC ": Proxy controller has issued an error");
        break;

    default:
        break;
    }
}
Ejemplo n.º 14
0
/**
 * mex_proxy_start_at:
 * @proxy: Proxy to add content to
 * @start_at_content: First content item in the model to add to
 * the proxy
 * @loop: Whether to loop back to the beginning of the
 * associated #MexModel's content items once the last item is reached;
 * if %TRUE, content items before the @start_at_content will be
 * added once the last of the model's content items is reached;
 * if %FALSE, only content items from @start_at_content to the last of
 * the model's content items are added
 *
 * Add content from a model to a proxy.
 */
void
mex_proxy_start_at (MexProxy   *proxy,
                    MexContent *start_at_content,
                    gboolean    loop)
{
  gint i;
  MexContent *content;
  MexProxyPrivate *priv;
  GController *controller;

  g_return_if_fail (MEX_IS_PROXY (proxy));

  priv = proxy->priv;

  if (priv->started)
    {
      g_warning (G_STRLOC ": Trying to start an already started proxy");
      return;
    }

  mex_proxy_clear (proxy);
  priv->started = TRUE;

  if (!priv->model)
    return;

  if (!G_TYPE_IS_OBJECT (priv->object_type))
    {
      g_warning (G_STRLOC ": Proxy type is not an object type");
      return;
    }

  /* Iterate over existing objects */
  if (!start_at_content)
    {
      i = 0;
      while ((content = mex_model_get_content (priv->model, i++)))
        mex_proxy_add_content (proxy, content);
    }
  else
    {
      gint start_at;
      gboolean looped = FALSE;

      start_at = mex_model_index (priv->model, start_at_content);

      if (start_at == -1)
        {
          g_critical (G_STRLOC ": Content %p not found in %p model",
                      start_at_content, priv->model);
          return;
        }

      for (i = start_at; TRUE; i++)
        {
          /* break out if looped and back around to start_at */
          if (loop && looped && i == start_at)
            break;

          if ((content = mex_model_get_content (priv->model, i)))
            {
              mex_proxy_add_content (proxy, content);
            }
          else
            {
              if (loop)
                {
                  looped = TRUE;
                  i = -1;
                }
              else
                break;
            }

        }
    }

  controller = mex_model_get_controller (priv->model);
  g_signal_connect_after (controller, "changed",
                          G_CALLBACK (mex_proxy_controller_changed_cb), proxy);
}
Ejemplo n.º 15
0
static void
mex_proxy_controller_changed_cb (GController          *controller,
                                 GControllerAction     action,
                                 GControllerReference *ref,
                                 MexProxy             *proxy)
{
  gint i, n_indices;
  MexContent *content;

  MexProxyPrivate *priv = proxy->priv;

  n_indices = g_controller_reference_get_n_indices (ref);

  switch (action)
    {
    case G_CONTROLLER_ADD:
      for (i = 0; i < n_indices; i++)
        {
          gint content_index = g_controller_reference_get_index_uint (ref, i);
          content = mex_model_get_content (priv->model, content_index);

          mex_proxy_add_content (proxy, content);
        }
      break;

    case G_CONTROLLER_REMOVE:
      {
        gint length, fillin = 0, start_fillin;
        GList *positions = NULL, *position;

        for (i = 0; i < n_indices; i++)
          {
            gint content_index = g_controller_reference_get_index_uint (ref, i);
            if (content_index >= priv->limit)
              positions = g_list_insert_sorted_with_data (positions,
                                                          GINT_TO_POINTER (content_index),
                                                          _insert_position,
                                                          NULL);
            else
              fillin++;
            content = mex_model_get_content (priv->model, content_index);
            mex_proxy_remove_content (proxy, content);
          }

        position = positions;
        length = mex_model_get_length (priv->model);
        start_fillin = priv->limit;
        for (i = 0;
             i < MIN (fillin, (length - (gint) priv->limit));
             i++)
          {
            if ((position != NULL) &&
                (start_fillin == GPOINTER_TO_INT (position->data)))
              {
                while ((position != NULL) &&
                       (start_fillin == GPOINTER_TO_INT (position->data)))
                  {
                    start_fillin++;
                    if (start_fillin > GPOINTER_TO_INT (position->data))
                      position = position->next;
                  }
              }
            content = mex_model_get_content (priv->model, start_fillin);
            mex_proxy_add_content (proxy, content);
            start_fillin++;
          }
        g_list_free (positions);
      }
      break;

    case G_CONTROLLER_UPDATE:
      /* Should be no need for this, GBinding sorts it out for us :) */
      break;

    case G_CONTROLLER_CLEAR:
      mex_proxy_clear (proxy);
      break;

    case G_CONTROLLER_REPLACE:
      mex_proxy_clear (proxy);
      i = 0;
      while ((content = mex_model_get_content (priv->model, i++)))
        mex_proxy_add_content (proxy, content);
      break;

    case G_CONTROLLER_INVALID_ACTION:
      g_warning (G_STRLOC ": Proxy controller has issued an error");
      break;

    default:
      g_warning (G_STRLOC ": Unhandled action");
      break;
    }
}
Ejemplo n.º 16
0
static void
mex_view_model_controller_changed_cb (GController          *controller,
                                      GControllerAction     action,
                                      GControllerReference *ref,
                                      MexViewModel         *self)
{
  gint n_indices, i;

  MexViewModelPrivate *priv = self->priv;

  n_indices = g_controller_reference_get_n_indices (ref);

  switch (action)
    {
    case G_CONTROLLER_ADD:
      {
        guint view_length;

        /* increase the internal items array by the number of new items */
        view_length = mex_model_get_length (MEX_MODEL (self));
        g_ptr_array_set_size (priv->internal_items, view_length + n_indices);

        /* set the new items */
        while (n_indices-- > 0)
          {
            MexContent *content;
            guint idx;

            idx = g_controller_reference_get_index_uint (ref, n_indices);

            content = mex_model_get_content (priv->model, idx);

            g_signal_connect (content, "notify", G_CALLBACK (content_notify_cb),
                              self);

            priv->internal_items->pdata[view_length + n_indices] = content;
          }
      }
      break;

    case G_CONTROLLER_REMOVE:
      {
        while (n_indices-- > 0)
          {
            MexContent *content;
            gint idx;

            idx = g_controller_reference_get_index_int (ref, n_indices);

            content = mex_model_get_content (priv->model, idx);

            g_signal_handlers_disconnect_by_func (content,
                                                  G_CALLBACK (content_notify_cb),
                                                  self);

            g_ptr_array_remove_fast (priv->internal_items, content);
          }
      }
      break;

    case G_CONTROLLER_UPDATE:
      /* Should be no need for this, GBinding sorts it out for us :) */
      break;

    case G_CONTROLLER_CLEAR:
      for (i = 0; i < priv->external_items->len; i++)
        g_object_unref (g_ptr_array_index (priv->external_items, i));
      g_ptr_array_set_size (priv->external_items, 0);

      for (i = 0; i < priv->external_items->len; i++)
        g_signal_handlers_disconnect_by_func (g_ptr_array_index (priv->external_items, i),
                                              G_CALLBACK (content_notify_cb),
                                              self);
      g_ptr_array_set_size (priv->internal_items, 0);
      break;

    case G_CONTROLLER_REPLACE:
      g_warning (G_STRLOC ": G_CONTROLLER_REPLACE not implemented by MexViewModel");
      break;

    case G_CONTROLLER_INVALID_ACTION:
      g_warning (G_STRLOC ": View-model controller has issued an error");
      break;

    default:
      g_warning (G_STRLOC ": Unhandled action");
      break;
    }

  mex_view_model_refresh_external_items (self);
}