示例#1
0
static void
_content_notify (MexContent     *content,
                 GParamSpec     *pspec,
                 MexContentTile *tile)
{
  MexContentTilePrivate *priv = tile->priv;
  const gchar *still_prop_name, *title_prop_name, *logo_prop_name;

  still_prop_name = mex_content_get_property_name (MEX_CONTENT (priv->content),
                                                   MEX_CONTENT_METADATA_STILL);
  title_prop_name = mex_content_get_property_name (MEX_CONTENT (priv->content),
                                                   MEX_CONTENT_METADATA_TITLE);
  logo_prop_name = mex_content_get_property_name (MEX_CONTENT (priv->content),
                                                  MEX_CONTENT_METADATA_STATION_LOGO);

  if (!g_strcmp0 (pspec->name, still_prop_name))
    {
      _reset_thumbnail (tile);
    }
  else if (!g_strcmp0 (pspec->name, title_prop_name))
    {
      _update_title (tile);
    }
  else if (!g_strcmp0 (pspec->name, logo_prop_name))
    {
      _update_logo (tile);
    }

}
int
main (int argc, char **argv)
{
  const ClutterColor grey = { 0x40, 0x40, 0x40, 0xff };

  ClutterActor *stage, *info_panel, *align;
  MxApplication *app;
  MxWindow *window;
  MexFeed *feed;
  MexProgram *program;

  mex_init (&argc, &argv);

  app = mx_application_new (&argc, &argv, "mex-info-panel-test", 0);
  mex_style_load_default ();

  window = mx_application_create_window (app);
  stage = (ClutterActor *) mx_window_get_clutter_stage (window);
  clutter_stage_set_color ((ClutterStage *) stage, &grey);

  align = g_object_new (MX_TYPE_FRAME, "x-align", MX_ALIGN_MIDDLE,
                        "y-align", MX_ALIGN_END, NULL);

  mx_window_set_child (window, align);

  info_panel = mex_info_panel_new (MEX_INFO_PANEL_MODE_FULL);
  mx_bin_set_child (MX_BIN (align), info_panel);

  mx_window_set_has_toolbar (window, FALSE);
  clutter_actor_set_size (stage, 1024, 768);

  feed = mex_feed_new ("source", "title");
  program =  mex_program_new (feed);

  mex_content_set_metadata (MEX_CONTENT (program),
                            MEX_CONTENT_METADATA_MIMETYPE,
                            "video/mp4");

  mex_content_set_metadata (MEX_CONTENT (program),
                            MEX_CONTENT_METADATA_TITLE,
                            "The cats on the moon");
  mex_content_set_metadata (MEX_CONTENT (program),
                            MEX_CONTENT_METADATA_SYNOPSIS,
                            "An original title where cats are sent to the moon to catch all the mice which are naturally attracted there due to the large consistency of cheese, this results in a space race between NASA and CATSA, leading to war on the moon over territory claimed by cats");
  mex_content_set_metadata (MEX_CONTENT (program),
                            MEX_CONTENT_METADATA_STILL,
                            "http://farm5.static.flickr.com/4013/4305303148_5cbc986a44_m.jpg");

  mex_content_view_set_content (MEX_CONTENT_VIEW (info_panel),
                                MEX_CONTENT (program));


  clutter_actor_show (stage);

  clutter_main ();

  return 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);
}
示例#4
0
void
mex_grilo_program_set_grilo_media (MexGriloProgram *program,
                                   GrlMedia        *media)
{
  MexGriloProgramPrivate *priv;

  g_return_if_fail (MEX_IS_GRILO_PROGRAM (program));
  g_return_if_fail (GRL_IS_MEDIA (media));

  priv = program->priv;

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

  if (priv->media != NULL)
    g_object_unref (priv->media);
  priv->media = g_object_ref (media);

  set_metadatas_from_media (MEX_CONTENT (program), media);

  /* Unset 'completed' so that the next time completed is called, all data
   * on this Grilo media is re-resolved.
   */
  priv->completed = FALSE;
}
示例#5
0
static void
mex_grilo_feed_open_default (MexGriloProgram *program, MexGriloFeed *feed)
{
  MexPlayer *player = mex_player_get_default ();

  mex_content_view_set_context (MEX_CONTENT_VIEW (player),
                                MEX_MODEL (feed));
  mex_content_view_set_content (MEX_CONTENT_VIEW (player),
                                MEX_CONTENT (program));
}
static void
tile_created_cb (MexProxy *proxy,
                 GObject  *content,
                 GObject  *object,
                 gpointer  controls)
{
    const gchar *mime_type;
    ClutterEffect *effect;
    ClutterColor color = { 0, 0, 0, 60 };

    /* filter out folders */
    mime_type = mex_content_get_metadata (MEX_CONTENT (content),
                                          MEX_CONTENT_METADATA_MIMETYPE);

    if (g_strcmp0 (mime_type, "x-grl/box") == 0)
    {
        g_signal_stop_emission_by_name (proxy, "object-created");
        return;
    }

    mex_tile_set_important (MEX_TILE (object), TRUE);
    clutter_actor_set_reactive (CLUTTER_ACTOR (object), TRUE);

    g_object_set (object, "thumb-height", 140, "thumb-width", 250, NULL);

    g_signal_connect (object, "key-press-event", G_CALLBACK (key_press_event_cb),
                      controls);
    g_signal_connect (object, "button-release-event",
                      G_CALLBACK (button_release_event_cb), controls);

    effect = g_object_new (MEX_TYPE_SHADOW,
                           "radius-x", 15,
                           "radius-y", 15,
                           "color", &color,
                           "enabled", FALSE,
                           NULL);
    clutter_actor_add_effect_with_name (CLUTTER_ACTOR (object), "shadow", effect);

    effect = g_object_new (MEX_TYPE_SHADOW,
                           "radius-x", 15,
                           "radius-y", 15,
                           "color", &color,
                           NULL);
    clutter_actor_add_effect_with_name (mx_bin_get_child (MX_BIN (object)),
                                        "shadow", effect);

    g_signal_connect (object, "focus-in", G_CALLBACK (tile_focus_in_cb), NULL);
    g_signal_connect (object, "focus-out", G_CALLBACK (tile_focus_out_cb), NULL);
    tile_focus_out_cb (MX_BIN (object));
}
示例#7
0
static char *
program_get_metadata_fallback (MexGenericContent *gc,
                               MexContentMetadata key)
{
  MexContent *content = MEX_CONTENT (gc);
  const gchar *showname;
  gchar *target;

  switch (key) {
  case MEX_CONTENT_METADATA_TITLE:
    showname = mex_content_get_metadata (content,
                                         MEX_CONTENT_METADATA_SERIES_NAME);

    if (!showname) {
      const gchar *url;
      gchar *basename;

      url = mex_content_get_metadata (content, MEX_CONTENT_METADATA_URL);
      basename = g_path_get_basename (url);
      target = g_uri_unescape_string (basename, NULL);
      g_free (basename);
    } else {
      const gchar *episode, *season;

      episode = mex_content_get_metadata (content,
                                          MEX_CONTENT_METADATA_EPISODE);
      season = mex_content_get_metadata (content,
                                         MEX_CONTENT_METADATA_SEASON);

      if (episode && season) {
        target = g_strdup_printf ("%s: Season %s, Episode %s",
                                  showname, season, episode);
      } else if (episode) {
        target = g_strdup_printf ("%s: Episode %s", showname, episode);
      } else if (season) {
        target = g_strdup_printf ("%s: Season %s", showname, season);
      } else {
        target = g_strdup (showname);
      }
    }
    break;

  default:
    target = NULL;
    break;
  }

  return target;
}
示例#8
0
static void
program_complete_cb (GrlMediaSource *source,
                     guint          operation_id,
                     GrlMedia       *media,
                     gpointer        userdata,
                     const GError   *error)
{
  MexGriloProgram *self = userdata;
  MexContent *content = MEX_CONTENT (self);

  set_metadatas_from_media (content, media);

  mex_grilo_program_thumbnail (content, media);

  g_object_unref (self);
  g_object_unref (source);
}
示例#9
0
static char *
_mex_program_get_index_str (MexProgram *program)
{
  GString *str;
  char *index_str;

  g_return_val_if_fail (MEX_IS_PROGRAM (program), NULL);

  str = g_string_new ("");
  mex_content_foreach_metadata (MEX_CONTENT (program),
                                make_metadata_string, str);

  index_str = str->str;
  g_string_free (str, FALSE);

  return index_str;
}
示例#10
0
static void
_mex_grilo_feed_content_updated (GrlSource *source,
                                 GPtrArray *changed_medias,
                                 GrlSourceChangeType change_type,
                                 gboolean known_location,
                                 MexGriloFeed *feed)
{
  gint i;
  GrlMedia *media;
  const gchar *id;
  MexGriloProgram *program;

  for (i = 0 ; i < changed_medias->len ; i++)
    {
      media =  g_ptr_array_index (changed_medias, i);
      id = grl_media_get_id (media);
      switch (change_type)
        {
        case GRL_CONTENT_CHANGED:
          program = MEX_GRILO_PROGRAM (mex_feed_lookup (MEX_FEED (feed), id));
          /* The policy might be slightly different here... */
          if (program != NULL) {
            mex_grilo_program_set_grilo_media (program, media);
          }
          break;

        case GRL_CONTENT_ADDED:
          program = MEX_GRILO_PROGRAM (mex_feed_lookup (MEX_FEED (feed), id));
          if (program != NULL) {
            mex_grilo_program_set_grilo_media (program, media);
          } else {
            emit_media_added (feed, media);
          }
          break;

        case GRL_CONTENT_REMOVED:
          program = MEX_GRILO_PROGRAM (mex_feed_lookup (MEX_FEED (feed), id));
          if (program != NULL) {
            mex_model_remove_content (MEX_MODEL (feed), MEX_CONTENT (program));
          }
          break;
        }
    }
}
示例#11
0
void
mex_program_get_thumbnail (MexProgram          *program,
                           MexGetThumbnailReply reply,
                           gpointer             userdata)
{
  MexProgramClass *klass;
  MexProgramPrivate *priv;
  const char *still;

  g_return_if_fail (MEX_IS_PROGRAM (program));
  priv = program->priv;

  /* Some backends (eg. Apple trailers) may be able to cache the stream
     so we can just use the standard metadata method to obtain it */
  still = mex_content_get_metadata (MEX_CONTENT (program),
                                    MEX_PROGRAM_METADATA_STILL);
  if (stream != NULL) {
    struct _GetStreamPayload *payload = g_slice_new (struct _GetStreamPayload);
    payload->program = g_object_ref (program);
    payload->reply = reply;
    payload->userdata = userdata;

    /* Technically the stream could be freed before the idle is called
       Great, now I want refcounted strings */
    payload->stream = g_strdup (stream);

    g_idle_add (emit_get_stream_reply, payload);
    return;
  }

  /* Other backends require custom methods to get the stream url */
  klass = MEX_PROGRAM_GET_CLASS (program);
  if (klass->get_stream) {
    klass->get_stream (program, reply, userdata);
  } else {
    struct _GetStreamPayload *payload = g_slice_new (struct _GetStreamPayload);
    payload->program = g_object_ref (program);
    payload->reply = reply;
    payload->userdata = userdata;
    payload->stream = NULL;

    g_idle_add (emit_get_stream_reply, payload);
  }
}
示例#12
0
/*
 * Callback from mex_thumbnailer_generate, when a thumbnail has been generated.
 */
static void
thumbnail_cb (const char *uri, gpointer user_data)
{
  MexContent *content;
  char *thumb_path;

  content = MEX_CONTENT (user_data);

  thumb_path = get_thumbnail_path_for_uri (uri);

  if (g_file_test (thumb_path, G_FILE_TEST_EXISTS))
    {
      gchar *thumb_uri = g_filename_to_uri (thumb_path, NULL, NULL);
      mex_grilo_program_set_metadata (content,
                                      MEX_CONTENT_METADATA_STILL,
                                      thumb_uri);
      g_free (thumb_uri);
    }

  g_free (thumb_path);
}
示例#13
0
static void
mex_grilo_program_get_stream_cb (GrlMediaSource *source,
                                 guint           operation_id,
                                 GrlMedia       *media,
                                 gpointer        userdata,
                                 const GError   *error)
{
  MexGriloProgramClosure *closure = userdata;
  MexContent *content = MEX_CONTENT (closure->self);
  const gchar *url = grl_media_get_url (media);

  MEX_CONTENT_IFACE (mex_grilo_program_parent_class)->set_metadata (content,
                                                                    MEX_CONTENT_METADATA_STREAM,
                                                                    url);

  closure->reply (MEX_PROGRAM (content),
                  url, error, closure->userdata);

  g_object_unref (content);
  g_object_unref (source);
  g_slice_free (MexGriloProgramClosure, closure);
}
示例#14
0
static void
mex_suggest_complete_cb (MexDownloadQueue *queue,
                         const gchar      *uri,
                         const gchar      *buffer,
                         gsize             count,
                         const GError     *error,
                         gpointer          userdata)
{
  RestXmlNode *root, *n;
  RestXmlParser *parser;
  MexSearchPlugin *self = userdata;
  MexSearchPluginPrivate *priv = self->priv;

  priv->suggest_id = NULL;

  /* hide spinner */
  mx_spinner_set_animating (MX_SPINNER (priv->spinner), FALSE);
  clutter_actor_hide (priv->spinner);

  if (error)
    {
      g_warning ("Error querying Google suggestions: %s",
                 error->message);
      return;
    }

  parser = rest_xml_parser_new ();
  root = rest_xml_parser_parse_from_data (parser, buffer, count);

  if (!root)
    {
      g_warning ("Unknown error parsing Google suggestions XML");
      g_object_unref (parser);
      return;
    }

  /* Clear model */
  mex_model_clear (MEX_MODEL (priv->suggest_model));

  /* Add new suggestions to model */
  n = rest_xml_node_find (root, "CompleteSuggestion");
  for (; n; n = n->next)
    {
      MexContent *content;
      const gchar *suggestion;

      RestXmlNode *node = rest_xml_node_find (n, "suggestion");

      if (!node)
        continue;

      suggestion = rest_xml_node_get_attr (node, "data");

      if (!suggestion)
        continue;

      content = MEX_CONTENT (mex_program_new (priv->suggest_model));
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_TITLE,
                                suggestion);
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_MIMETYPE,
                                "x-mex/search");
      mex_model_add_content (MEX_MODEL (priv->suggest_model), content);
    }

  /* Unref */
  rest_xml_node_unref (root);
  g_object_unref (parser);
}
示例#15
0
static void
mex_search_plugin_update_history (MexSearchPlugin *self,
                                  const gchar     *term)
{
  gint i;
  gsize length;
  gchar *contents, *current;

  MexSearchPluginPrivate *priv = self->priv;
  const gchar *base_dir =
    mex_settings_get_config_dir (mex_settings_get_default ());
  gchar *history_file = g_build_filename (base_dir, "search", "history", NULL);

  /* Read the history file contents */
  /* TODO: Make this less rubbish? */
  g_file_get_contents (history_file, &contents, &length, NULL);

  /* Prepend new search-term if appropriate */
  if (term)
    {
      gint terms;
      gchar *path;
      gsize new_length;

      gsize term_len = strlen (term);
      gchar *new_contents = g_malloc (length + term_len + 1);

      memcpy (new_contents, term, term_len);
      new_contents[term_len] = '\n';
      new_length = term_len + 1;

      /* Truncate list to 10 terms and remove duplicates */
      if (contents)
        {
          i = 0;
          terms = 1;
          do
            {
              gint cur_len;
              char *eos = strchr (contents + i, '\n');

              if (!eos)
                cur_len = strlen (contents + i);
              else
                cur_len = eos - (contents + i);

              if ((cur_len != term_len) ||
                  (strncmp (contents + i, term, term_len) != 0))
                {
                  memcpy (new_contents + new_length, contents + i, cur_len + 1);
                  new_length += cur_len + 1;

                  if (++terms >= 10)
                    break;
                }

              if (!eos)
                break;

              i += cur_len + 1;
            } while (i < length);
        }

      new_contents[new_length++] = '\0';

      /* Save new list */
      path = g_path_get_dirname (history_file);
      g_mkdir_with_parents (path, 0755);
      g_free (path);

      g_file_set_contents (history_file, new_contents, new_length, NULL);

      /* Replace content with new content */
      g_free (contents);
      contents = new_contents;
      length = new_length;
    }

  /* Empty current list */
  mex_model_clear (MEX_MODEL (priv->history_model));

  /* Populate with search history */
  if (contents)
    {
      current = contents;
      while (current < contents + length)
        {
          MexContent *content =
            MEX_CONTENT (mex_program_new (priv->history_model));
          gchar *end = g_utf8_strchr (current, -1, '\n');

          if (end)
            *end = '\0';

          if (*current)
            {
              mex_content_set_metadata (content,
                                        MEX_CONTENT_METADATA_TITLE,
                                        current);
              mex_content_set_metadata (content,
                                        MEX_CONTENT_METADATA_MIMETYPE,
                                        "x-mex/search");
              mex_model_add_content (MEX_MODEL (priv->history_model),
                                     content);
            }

          if (end)
            current = end + 1;
          else
            break;
        }

      g_free (contents);
    }
  else
    {
      /* Add a default search so the column isn't hidden.
       * TODO: Have a way of inserting 'stock' content rather than doing
       *       this, I suppose.
       */
      MexContent *content = MEX_CONTENT (mex_program_new (priv->history_model));
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_TITLE, "MeeGo");
      mex_content_set_metadata (content, MEX_CONTENT_METADATA_MIMETYPE,
                                "x-mex/search");
      mex_model_add_content (MEX_MODEL (priv->history_model), content);
    }
}