예제 #1
0
ClutterActor *
mex_telepathy_channel_create_static_image (void)
{
  ClutterActor *actor;

  gchar *static_image_path;
  GError *error = NULL;

  static_image_path = g_build_filename (mex_get_data_dir (),
                                        "style",
                                        "thumb-call-pip-off.png",
                                        NULL);

  actor = clutter_texture_new_from_file (static_image_path,
                    &error);
  if (error)
  {
    g_warning ("Error loading texture %s", error->message);
    g_clear_error (&error);
  }

  if (static_image_path)
    g_free (static_image_path);

  clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE
                                         (actor), TRUE);

  return actor;
}
예제 #2
0
/*
 * If we need to, generate a thumbnail.
 *
 * If the URL is not file:/// then we assume it's okay to use.
 *
 */
static void
mex_grilo_program_thumbnail (MexContent *content, GrlMedia *media)
{
  const char *url;
  char *thumb_path;

  /* If the media isn't local, then we'll ignore it for now */
  url = grl_media_get_url (media);
  if (url == NULL || !g_str_has_prefix (url, "file:///"))
    return;

  if (GRL_IS_MEDIA_BOX (media))
    {
      gchar *tmp;

      tmp = g_build_filename (mex_get_data_dir (), "common", "folder-tile.png",
                              NULL);
      mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, tmp);
      g_free (tmp);
      return;
    }

  /*
   * If we're already got a thumbnail, see if we're happy with it or want to
   * ignore it.
   */
  thumb_path = (char*)mex_content_get_metadata (content,
                                                MEX_CONTENT_METADATA_STILL);
  if (thumb_path) {
    /* If the thumbnail is already a good one, we're done */
    if (thumb_path && strstr (thumb_path, "/.thumbnails/x-huge/"))
      return;

    /*
     * If the thumbnail currently set is a "normal" thumbnail we ignore it on the
     * basis that it's likely to have been generated by Totem, and thus is bad.
     * If your platform doesn't have Totem then this can be removed!
     */
    if (thumb_path && strstr (thumb_path, "/.thumbnails/normal/"))
      mex_grilo_program_set_metadata (content, MEX_CONTENT_METADATA_STILL, NULL);
  }

  /*
   * Now see if we've a thumbnail generated already.  TODO: use the Tumbler API
   * to do this.
   */
  thumb_path = get_thumbnail_path_for_uri (url);
  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);
  } else {
    mex_thumbnailer_generate (url, grl_media_get_mime (media),
                              thumbnail_cb, content);
  }
  g_free (thumb_path);
}
예제 #3
0
static void
mex_info_bar_init (MexInfoBar *self)
{
  ClutterScript *script;
  ClutterActor *notification_area;
  GError *err = NULL;
  gchar *tmp;

  MexInfoBarPrivate *priv = self->priv = INFO_BAR_PRIVATE (self);

  priv->script = script = clutter_script_new ();

  tmp = g_build_filename (mex_get_data_dir (), "json", "info-bar.json", NULL);
  clutter_script_load_from_file (script, tmp, &err);
  g_free (tmp);

  if (err)
    g_error ("Could not load info bar: %s", err->message);

  priv->group =
    CLUTTER_ACTOR (clutter_script_get_object (script, "main-group"));

  clutter_actor_set_parent (priv->group, CLUTTER_ACTOR (self));


  priv->settings_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "settings-button"));

  priv->power_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "power-button"));

  priv->back_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "back-button"));

  priv->notification_source = mex_generic_notification_source_new ();

  notification_area =
    CLUTTER_ACTOR (clutter_script_get_object (priv->script,
                                              "notification-area"));

  mex_notification_area_add_source (MEX_NOTIFICATION_AREA (notification_area),
                                    MEX_NOTIFICATION_SOURCE (priv->notification_source));

  g_signal_connect (priv->settings_button,
                    "clicked",
                    G_CALLBACK (_show_settings_dialog_cb), self);

  g_signal_connect (priv->power_button,
                    "clicked",
                    G_CALLBACK (_show_power_dialog_cb), self);

  g_signal_connect (priv->back_button,
                    "clicked",
                    G_CALLBACK (_back_button_cb), self);

  _create_power_dialog (MEX_INFO_BAR (self));
  _create_settings_dialog (MEX_INFO_BAR (self));
}
예제 #4
0
void
mex_player_set_idle_mode (MexPlayer *player,
                          gboolean   idle)
{
  MexPlayerPrivate *priv = player->priv;

  if (priv->idle_mode == idle)
    return;

  priv->idle_mode = idle;

  mex_player_set_controls_visible (player, !idle);

  if (idle)
    {
      gchar *tmp;

      clutter_actor_hide (priv->controls);
      clutter_actor_hide (priv->info_panel);
      mx_widget_set_disabled (MX_WIDGET (player), TRUE);
      clutter_actor_set_reactive (CLUTTER_ACTOR (player), FALSE);

      if (priv->content) {
        save_old_content (player);
        g_object_unref (priv->content);
        priv->content = NULL;
      }

      tmp = g_strconcat ("file://", mex_get_data_dir (),
                         "/common/style/background-loop.mkv", NULL);
      clutter_media_set_uri (priv->media, tmp);
      g_free (tmp);

      clutter_media_set_playing (priv->media, TRUE);

      /* we're idle so we don't mind the screensaver coming on */
       mex_screensaver_uninhibit (priv->screensaver);
    }
  else
    {
      clutter_actor_show (priv->controls);
      clutter_actor_show (priv->info_panel);
      mx_widget_set_disabled (MX_WIDGET (player), FALSE);
      clutter_actor_set_reactive (CLUTTER_ACTOR (player), TRUE);
      clutter_media_set_playing (priv->media, FALSE);
      clutter_media_set_uri (priv->media, NULL);

      /* we're playing real content so don't allow the screensaver */
      mex_screensaver_inhibit (priv->screensaver);
    }
}
예제 #5
0
static struct lirc_config *
mex_lirc_init (const gchar *name)
{
  int lirc_fd, res;
  gchar *tmp;

  lirc_fd = lirc_init ((char *)name, 1);

  if (lirc_fd == -1)
    g_warning (G_STRLOC ": LIRC initialisation failed");
  else
    {
      struct lirc_config *config = NULL;

      /* Load the default config */
      tmp = g_build_filename (mex_get_data_dir (), "mex-lircrc", NULL);
      res = lirc_readconfig (tmp, &config, NULL);
      g_free (tmp);

      if (res == 0)
        {
          int flags;
          GIOChannel *channel;

          /* Set non-blocking flag */
          flags = fcntl (lirc_fd, F_GETFL);
          fcntl (lirc_fd, F_SETFL, flags | O_NONBLOCK);

          /* Create IOChannel to do non-blocking reads */
          channel = g_io_channel_unix_new (lirc_fd);
          g_io_add_watch (channel,
                          G_IO_IN | G_IO_PRI | G_IO_ERR |
                          G_IO_NVAL | G_IO_HUP,
                          (GIOFunc)mex_lirc_read_cb,
                          config);

          return config;
        }
      else
        {
          g_warning (G_STRLOC ": Error reading LIRC config");
          lirc_deinit ();
        }
    }

  return NULL;
}
예제 #6
0
static void
mex_telepathy_channel_create_toolbar (MexTelepathyChannel *self)
{
  MexTelepathyChannelPrivate *priv = MEX_TELEPATHY_CHANNEL (self)->priv;

  gchar *static_image_path;
  ClutterActor *toolbar;

  MxAction *end_action;
  MxAction *camera_action;
  MxAction *mute_action;
  GError *error = NULL;

  // Create the user label
  priv->avatar_image = mx_image_new ();
  static_image_path = g_build_filename (mex_get_data_dir (),
                                        "style",
                                        "thumb-call-avatar-small.png",
                                        NULL);
  mx_image_set_from_file (MX_IMAGE (priv->avatar_image),
                          static_image_path,
                          &error);

  if (error)
  {
    g_warning ("Error loading texture %s", error->message);
    g_clear_error (&error);
  }

  if (static_image_path)
    g_free (static_image_path);

  priv->title_label = mx_label_new ();
  mx_label_set_y_align (MX_LABEL (priv->title_label), MX_ALIGN_MIDDLE);
  mx_label_set_x_align (MX_LABEL (priv->title_label), MX_ALIGN_MIDDLE);

  end_action =
    mx_action_new_full ("End",
                        "Hang Up",
                        G_CALLBACK (mex_telepathy_channel_on_hangup),
                        self);

  priv->end_button = mex_action_button_new (end_action);
  mx_stylable_set_style_class (MX_STYLABLE (priv->end_button), "EndCall");

  camera_action =
    mx_action_new_full("Camera",
                       "Camera Off",
                       G_CALLBACK (mex_telepathy_channel_toggle_camera),
                       self);

  priv->camera_button = mex_action_button_new (camera_action);
  /* off by default */
  mex_telepathy_channel_set_camera_state (self, FALSE);

  mute_action =
    mx_action_new_full("Mute",
                       "Mic Off",
                       G_CALLBACK (mex_telepathy_channel_toggle_mute),
                       self);

  priv->mute_button = mex_action_button_new (mute_action);
  mx_stylable_set_style_class (MX_STYLABLE (priv->mute_button), "MediaMute");

  toolbar = mx_box_layout_new ();
  clutter_actor_set_width (toolbar, 980);
  clutter_actor_set_height (toolbar, 48);
  mx_stylable_set_style_class (MX_STYLABLE (toolbar),
                               "MexCallControlsTitle");
  // Put the buttons in the toolbar
  mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar),
                                           priv->avatar_image,
                                           0,
                                           "expand",
                                           FALSE,
                                           "x-align",
                                           MX_ALIGN_END,
                                           "x-fill",
                                           FALSE,
                                           NULL);

  mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar),
                                           priv->title_label,
                                           1,
                                           "expand",
                                           TRUE,
                                           NULL);

  mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar),
                                           priv->camera_button,
                                           2,
                                           "expand",
                                           TRUE,
                                           NULL);

  mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar),
                                           priv->mute_button,
                                           3,
                                           "expand",
                                           TRUE,
                                           NULL);

  mx_box_layout_add_actor_with_properties (MX_BOX_LAYOUT (toolbar),
                                           priv->end_button,
                                           4,
                                           "expand",
                                           TRUE,
                                           NULL);

  priv->toolbar_area = mx_frame_new ();
  mx_bin_set_child (MX_BIN (priv->toolbar_area), toolbar);
  mx_stylable_set_style_class (MX_STYLABLE (priv->toolbar_area),
                               "ToolbarArea");
}
예제 #7
0
static void
mex_info_bar_init (MexInfoBar *self)
{
  ClutterScript *script;
  ClutterActor *notification_area;
  GError *err = NULL;
  gchar *tmp;
  GSettings *settings;

  MexInfoBarPrivate *priv = self->priv = INFO_BAR_PRIVATE (self);

  priv->script = script = clutter_script_new ();

  tmp = g_build_filename (mex_get_data_dir (), "json", "info-bar.json", NULL);
  clutter_script_load_from_file (script, tmp, &err);
  g_free (tmp);

  if (err)
    g_error ("Could not load info bar: %s", err->message);

  priv->group =
    CLUTTER_ACTOR (clutter_script_get_object (script, "main-group"));

  clutter_actor_set_parent (priv->group, CLUTTER_ACTOR (self));


  priv->settings_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "settings-button"));

  priv->power_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "power-button"));

  priv->back_button =
    CLUTTER_ACTOR (clutter_script_get_object (script, "back-button"));

  priv->notification_source = mex_generic_notification_source_new ();

  notification_area =
    CLUTTER_ACTOR (clutter_script_get_object (priv->script,
                                              "notification-area"));

  /* ensure the notification area is above any other actors */
  clutter_actor_set_child_above_sibling (clutter_actor_get_parent (notification_area),
                                         notification_area, NULL);

  mex_notification_area_add_source (MEX_NOTIFICATION_AREA (notification_area),
                                    MEX_NOTIFICATION_SOURCE (priv->notification_source));

  g_signal_connect (priv->settings_button,
                    "clicked",
                    G_CALLBACK (_show_settings_dialog_cb), self);

  g_signal_connect (priv->power_button,
                    "clicked",
                    G_CALLBACK (_close_request_cb), self);

  g_signal_connect (priv->back_button,
                    "clicked",
                    G_CALLBACK (_back_button_cb), self);

  _create_settings_dialog (MEX_INFO_BAR (self));

  settings = g_settings_new ("org.media-explorer.Shell");
  if (!g_settings_get_boolean (settings, "close-button-visible"))
    clutter_actor_hide (priv->power_button);
  g_clear_object (&settings);
}
예제 #8
0
static gboolean
_create_settings_dialog (MexInfoBar *self)
{
  MexInfoBarPrivate *priv = self->priv;

  ClutterActor *dialog, *network_graphic;
  ClutterActor *network_tile, *dialog_layout, *dialog_label;
  ClutterActor *network_button;

  MxAction *close_dialog, *network_settings;

  dialog = mx_dialog_new ();
  mx_stylable_set_style_class (MX_STYLABLE (dialog), "MexInfoBarDialog");

  dialog_label = mx_label_new_with_text (_("Settings"));
  mx_stylable_set_style_class (MX_STYLABLE (dialog_label), "DialogHeader");

  /* Create actions for settings dialog */
  network_settings =
    _action_new_from_desktop_file ("mex-networks.desktop");

  close_dialog = mx_action_new_full ("close", _("Close"),
                                     G_CALLBACK (_close_dialog_cb), self);

  dialog_layout = mx_table_new ();
  mx_table_set_column_spacing (MX_TABLE (dialog_layout), 10);
  mx_table_set_row_spacing (MX_TABLE (dialog_layout), 30);

  mx_table_insert_actor (MX_TABLE (dialog_layout),
                         CLUTTER_ACTOR (dialog_label), 0, 0);

  if (network_settings)
    {
      gchar *tmp;
      network_graphic = mx_image_new ();
      mx_stylable_set_style_class (MX_STYLABLE (network_graphic),
                                   "NetworkGraphic");

      tmp = g_build_filename (mex_get_data_dir (), "style",
                              "graphic-network.png", NULL);
      mx_image_set_from_file (MX_IMAGE (network_graphic), tmp, NULL);
      g_free (tmp);

      network_tile = mex_tile_new ();
      mex_tile_set_label (MEX_TILE (network_tile), _("Network"));
      mex_tile_set_important (MEX_TILE (network_tile), TRUE);

      network_button = mx_button_new ();

      mx_button_set_action (MX_BUTTON (network_button), network_settings);

      mx_bin_set_child (MX_BIN (network_tile), network_button);
      mx_bin_set_child (MX_BIN (network_button), network_graphic);

      mx_table_insert_actor (MX_TABLE (dialog_layout),
                             CLUTTER_ACTOR (network_tile), 1, 1);
    }

  if (!network_settings)
    {
      ClutterActor *no_settings;
      no_settings = mx_label_new_with_text (_("No settings helpers installed"));

      clutter_actor_destroy (priv->settings_button);

      mx_table_insert_actor (MX_TABLE (dialog_layout),
                             CLUTTER_ACTOR (no_settings), 1, 0);
    }


  mx_bin_set_child (MX_BIN (dialog), dialog_layout);
  mx_dialog_add_action (MX_DIALOG (dialog), close_dialog);

  priv->settings_dialog = g_object_ref (dialog);

  return TRUE;
}
예제 #9
0
static void
mex_media_controls_init (MexMediaControls *self)
{
    ClutterActor *actor;
    ClutterScript *script;
    GError *err = NULL;
    MxAdjustment *adjustment;
    ClutterActor *related_box;
    gchar *tmp;

    MexMediaControlsPrivate *priv = self->priv = MEDIA_CONTROLS_PRIVATE (self);

    priv->script = script = clutter_script_new ();

    tmp = g_build_filename (mex_get_data_dir (), "json", "media-controls.json",
                            NULL);
    clutter_script_load_from_file (script, tmp, &err);
    g_free (tmp);

    if (err)
        g_error ("Could not load media controls interface: %s", err->message);

    priv->vbox =
        (ClutterActor*) clutter_script_get_object (script, "media-controls");
    clutter_actor_set_parent (priv->vbox, CLUTTER_ACTOR (self));

    /* add shadow to media controls box */
    actor = (ClutterActor *) clutter_script_get_object (script,
            "media-controls-box");
    clutter_actor_add_effect (actor, CLUTTER_EFFECT (mex_shadow_new ()));


    /* vertical fade effect */
    priv->vertical_effect = mx_fade_effect_new ();
    clutter_actor_add_effect (priv->vbox, priv->vertical_effect);
    mx_scrollable_get_adjustments (MX_SCROLLABLE (mx_bin_get_child (MX_BIN (priv->vbox))),
                                   NULL, &adjustment);
    g_signal_connect (adjustment, "changed",
                      G_CALLBACK (notify_vertical_changed_cb), self);
    g_signal_connect (adjustment, "notify::value",
                      G_CALLBACK (notify_vertical_value_cb), self);

    /* horizontal fade effect */
    priv->horizontal_effect = mx_fade_effect_new ();
    related_box = (ClutterActor *) clutter_script_get_object (priv->script,
                  "related-box");
    clutter_actor_add_effect (related_box, priv->horizontal_effect);
    mx_scrollable_get_adjustments (MX_SCROLLABLE (related_box), &adjustment,
                                   NULL);
    g_signal_connect (adjustment, "changed",
                      G_CALLBACK (notify_horizontal_changed_cb), self);
    g_signal_connect (adjustment, "notify::value",
                      G_CALLBACK (notify_horizontal_value_cb), self);


    /* slider setup */
    priv->slider = (ClutterActor*) clutter_script_get_object (script, "slider");
    g_signal_connect (priv->slider, "notify::value",
                      G_CALLBACK (slider_value_changed_cb), self);
    g_signal_connect (priv->slider, "captured-event",
                      G_CALLBACK (slider_captured_event), self);

    priv->play_pause_action =
        (MxAction*) clutter_script_get_object (script, "play-pause-action");

    priv->stop_action =
        (MxAction*) clutter_script_get_object (script, "stop-action");

    priv->add_to_queue_action =
        (MxAction*) clutter_script_get_object (script, "add-to-queue-action");

    priv->queue_button =
        (ClutterActor *) clutter_script_get_object (script, "add-to-queue-button");

    g_signal_connect (priv->play_pause_action, "activated",
                      G_CALLBACK (mex_media_controls_play_cb), self);
    g_signal_connect (priv->stop_action, "activated",
                      G_CALLBACK (mex_media_controls_stop_cb), self);
#if 0
    g_signal_connect (priv->add_to_queue_action, "activated",
                      G_CALLBACK (mex_media_controls_add_to_queue_cb), self);
#endif

    /* proxy setup */

    priv->proxy_model = MEX_VIEW_MODEL (mex_view_model_new (NULL));
    /* FIXME: Set an arbitrary 200-item limit as we can't handle large
     *        amounts of actors without massive slow-down.
     */
    mex_view_model_set_limit (priv->proxy_model, 200);

    priv->proxy = mex_content_proxy_new (MEX_MODEL (priv->proxy_model),
                                         CLUTTER_CONTAINER (related_box),
                                         MEX_TYPE_CONTENT_TILE);

    g_signal_connect (priv->proxy, "object-created", G_CALLBACK (tile_created_cb),
                      self);

    priv->is_disabled = TRUE;
}
예제 #10
0
static void
_reset_thumbnail (MexContentTile *tile)
{
  MexContentTilePrivate *priv = tile->priv;
  MexDownloadQueue *queue = mex_download_queue_get_default ();
  const gchar *mime = NULL;
  gchar *placeholder_filename = NULL;

  queue = mex_download_queue_get_default ();

  /* cancel any download already in progress */
  if (priv->download_id)
    {
      mex_download_queue_cancel (queue, priv->download_id);
      priv->download_id = NULL;
    }

  priv->thumbnail_loaded = FALSE;

  /* Load placeholder image */
  if (priv->content)
    mime = mex_content_get_metadata (priv->content,
                                     MEX_CONTENT_METADATA_MIMETYPE);

  if (mime && g_str_has_prefix (mime, "image/"))
    {
      placeholder_filename = "thumb-image.png";
    }
  else if (mime && g_str_equal (mime, "x-mex/tv"))
    {
      placeholder_filename = "thumb-tv.png";
    }
  else if (mime && g_str_equal (mime, "video/dvd"))
    {
      placeholder_filename = "thumb-disc.png";
    }
  else if (mime && (g_str_has_prefix (mime, "video/") ||
                    g_str_equal (mime, "x-mex/media")))
    {
      placeholder_filename = "thumb-video.png";
    }
  else if (mime && (g_str_has_prefix (mime, "audio/")))
    {
      placeholder_filename = "thumb-music.png";
    }
  else if (mime && g_str_equal (mime, "x-grl/box"))
    {
      placeholder_filename = "folder-tile.png";
    }
  else if (mime && g_str_equal (mime, "x-mex/group"))
    {
      placeholder_filename = "folder-tile.png";
    }
  else if (mime && g_str_equal (mime, "x-mex/app"))
    {
      placeholder_filename = "thumb-app.png";
    }

  if (placeholder_filename)
    {
      gchar *tmp;
      const gchar *dir = mex_get_data_dir ();

      tmp = g_build_filename (dir, "style", placeholder_filename, NULL);
      _update_thumbnail_from_image (tile, tmp);
      g_free (tmp);
    }
  else
    {
      mx_image_clear (MX_IMAGE (priv->image));

      /* Reset the height - really, we ought to reset the width and height,
       * but for all our use-cases, we want to keep the set width.
       */
      clutter_actor_set_height (priv->image, -1);
      priv->image_set = FALSE;

      return;
    }

  clutter_actor_set_size (priv->image,
                          priv->thumb_width, priv->thumb_height);
}