Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Gnome/gtk/   (Gnome Linux Desktop Version 4.23.2©)  Datei vom 30.5.2026 mit Größe 16 kB image not shown  

Quelle  gtkmediafile.c

  Sprache: C
 

/*
 * Copyright © 2018 Benjamin Otte
 *
 * 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, see <http://www.gnu.org/licenses/>.
 *
 * Authors: Benjamin Otte <otte@gnome.org>
 */


#include "config.h"

#include "gtkmediafileprivate.h"

#include "gtkdebug.h"
#include "gtkprivate.h"
#include <glib/gi18n-lib.h>
#include "gtkmodulesprivate.h"
#include "gtknomediafileprivate.h"
#ifdef HAVE_GSTREAMER
#include "media/gtkgstmediafileprivate.h"
#endif

/**
 * GtkMediaFile:
 *
 * Implements the `GtkMediaStream` interface for files.
 *
 * This provides a simple way to play back video files with GTK.
 *
 * GTK provides a GIO extension point for `GtkMediaFile` implementations
 * to allow for external implementations using various media frameworks.
 *
 * GTK itself includes an implementation using GStreamer.
 */


typedef struct _GtkMediaFilePrivate GtkMediaFilePrivate;

struct _GtkMediaFilePrivate
{
  GFile *file;
  GInputStream *input_stream;
};

enum {
  PROP_0,
  PROP_FILE,
  PROP_INPUT_STREAM,

  N_PROPS,
};

static GParamSpec *properties[N_PROPS] = { NULL, };

G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkMediaFile, gtk_media_file, GTK_TYPE_MEDIA_STREAM,
                                  G_ADD_PRIVATE (GtkMediaFile))

#define GTK_MEDIA_FILE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
  g_critical ("Media file of type '%s' does not implement GtkMediaFile::" method, G_OBJECT_TYPE_NAME (obj))

static void
gtk_media_file_default_open (GtkMediaFile *self)
{
  GTK_MEDIA_FILE_WARN_NOT_IMPLEMENTED_METHOD (self, open);
}

static void
gtk_media_file_default_close (GtkMediaFile *self)
{
  gtk_media_stream_stream_unprepared (GTK_MEDIA_STREAM (self));
}

static void
gtk_media_file_set_property (GObject      *object,
                             guint         prop_id,
                             const GValue *value,
                             GParamSpec   *pspec)

{
  GtkMediaFile *self = GTK_MEDIA_FILE (object);

  switch (prop_id)
    {
    case PROP_FILE:
      gtk_media_file_set_file (self, g_value_get_object (value));
      break;

    case PROP_INPUT_STREAM:
      gtk_media_file_set_input_stream (self, g_value_get_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_media_file_get_property (GObject    *object,
                             guint       prop_id,
                             GValue     *value,
                             GParamSpec *pspec)
{
  GtkMediaFile *self = GTK_MEDIA_FILE (object);
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  switch (prop_id)
    {
    case PROP_FILE:
      g_value_set_object (value, priv->file);
      break;

    case PROP_INPUT_STREAM:
      g_value_set_object (value, priv->input_stream);
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void
gtk_media_file_dispose (GObject *object)
{
  GtkMediaFile *self = GTK_MEDIA_FILE (object);
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_clear_object (&priv->file);
  g_clear_object (&priv->input_stream);

  G_OBJECT_CLASS (gtk_media_file_parent_class)->dispose (object);
}

static void
gtk_media_file_class_init (GtkMediaFileClass *class)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (class);

  class->open = gtk_media_file_default_open;
  class->close = gtk_media_file_default_close;

  gobject_class->set_property = gtk_media_file_set_property;
  gobject_class->get_property = gtk_media_file_get_property;
  gobject_class->dispose = gtk_media_file_dispose;

  /**
   * GtkMediaFile:file:
   *
   * The file being played back or %NULL if not playing a file.
   */

  properties[PROP_FILE] =
    g_param_spec_object ("file", NULL, NULL,
                         G_TYPE_FILE,
                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_NAME);

  /**
   * GtkMediaFile:input-stream:
   *
   * The stream being played back or %NULL if not playing a stream.
   *
   * This is %NULL when playing a file.
   */

  properties[PROP_INPUT_STREAM] =
    g_param_spec_object ("input-stream", NULL, NULL,
                         G_TYPE_INPUT_STREAM,
                         G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_NAME);

  g_object_class_install_properties (gobject_class, N_PROPS, properties);
}

static void
gtk_media_file_init (GtkMediaFile *self)
{
}

GIOExtension *
gtk_media_file_get_extension (void)
{
  const char *extension_name;
  GIOExtension *e;
  GIOExtensionPoint *ep;

  g_type_ensure (GTK_TYPE_NO_MEDIA_FILE);

#ifdef HAVE_MEDIA_GSTREAMER
  g_type_ensure (GTK_TYPE_GST_MEDIA_FILE);
#endif

  GTK_DEBUG (MODULES, "Looking up MediaFile extension");

  g_type_ensure (GTK_TYPE_NO_MEDIA_FILE);

#ifdef HAVE_GSTREAMER
  g_type_ensure (GTK_TYPE_GST_MEDIA_FILE);
#endif

  ep = g_io_extension_point_lookup (GTK_MEDIA_FILE_EXTENSION_POINT_NAME);
  e = NULL;

  extension_name = g_getenv ("GTK_MEDIA");
  if (extension_name)
    {
      if (g_str_equal (extension_name, "help"))
        {
          GList *l;

          g_print ("Supported arguments for GTK_MEDIA environment variable:\n");

          for (l = g_io_extension_point_get_extensions (ep); l; l = l->next)
            {
              e = l->data;

              g_print ("%10s - %d\n", g_io_extension_get_name (e), g_io_extension_get_priority (e));
            }

          e = NULL;
        }
      else
        {
          e = g_io_extension_point_get_extension_by_name (ep, extension_name);
          if (e == NULL)
            {
              g_warning ("Media extension \"%s\" from GTK_MEDIA environment variable not found.", extension_name);
            }
        }
    }

  if (e == NULL)
    {
      GList *l = g_io_extension_point_get_extensions (ep);

      if (l == NULL)
        {
          g_error ("GTK was run without any GtkMediaFile extension being present. This must not happen.");
        }

      e = l->data;
    }

  return e;
}

static GType
gtk_media_file_get_impl_type (void)
{
  static GType impl_type = G_TYPE_NONE;
  GIOExtension *e;

  if (G_LIKELY (impl_type != G_TYPE_NONE))
    return impl_type;

  e = gtk_media_file_get_extension ();
  impl_type = g_io_extension_get_type (e);

  GTK_DEBUG (MODULES, "Using %s from \"%s\" extension",
             g_type_name (impl_type), g_io_extension_get_name (e));

  return impl_type;
}

/**
 * gtk_media_file_new:
 *
 * Creates a new empty media file.
 *
 * Returns: (type Gtk.MediaFile): a new `GtkMediaFile`
 **/

GtkMediaStream *
gtk_media_file_new (void)
{
  return g_object_new (gtk_media_file_get_impl_type (), NULL);
}

/**
 * gtk_media_file_new_for_filename:
 * @filename: (type filename): filename to open
 *
 * Creates a new media file for the given filename.
 *
 * This is a utility function that converts the given @filename
 * to a `GFile` and calls [ctor@Gtk.MediaFile.new_for_file].
 *
 * Returns: (type Gtk.MediaFile): a new `GtkMediaFile` playing @filename
 */

GtkMediaStream *
gtk_media_file_new_for_filename (const char *filename)
{
  GtkMediaStream *result;
  GFile *file;

  if (filename)
    file = g_file_new_for_path (filename);
  else
    file = NULL;

  result = gtk_media_file_new_for_file (file);

  if (file)
    g_object_unref (file);

  return result;
}

/**
 * gtk_media_file_new_for_resource:
 * @resource_path: resource path to open
 *
 * Creates a new new media file for the given resource.
 *
 * This is a utility function that converts the given @resource
 * to a `GFile` and calls [ctor@Gtk.MediaFile.new_for_file].
 *
 * Returns: (type Gtk.MediaFile): a new `GtkMediaFile` playing @resource_path
 */

GtkMediaStream *
gtk_media_file_new_for_resource (const char *resource_path)
{
  GtkMediaStream *result;
  GFile *file;

  if (resource_path)
    {
      char *uri, *escaped;

      escaped = g_uri_escape_string (resource_path,
                                     G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
      uri = g_strconcat ("resource://", escaped, NULL);
      g_free (escaped);

      file = g_file_new_for_uri (uri);
      g_free (uri);
    }
  else
    {
      file = NULL;
    }

  result = gtk_media_file_new_for_file (file);

  if (file)
    g_object_unref (file);

  return result;
}

/**
 * gtk_media_file_new_for_file:
 * @file: The file to play
 *
 * Creates a new media file to play @file.
 *
 * Returns: (type Gtk.MediaFile): a new `GtkMediaFile` playing @file
 */

GtkMediaStream *
gtk_media_file_new_for_file (GFile *file)
{
  g_return_val_if_fail (file == NULL || G_IS_FILE (file), NULL);

  return g_object_new (gtk_media_file_get_impl_type (),
                       "file", file,
                       NULL);
}

/**
 * gtk_media_file_new_for_input_stream:
 * @stream: The stream to play
 *
 * Creates a new media file to play @stream.
 *
 * If you want the resulting media to be seekable,
 * the stream should implement the `GSeekable` interface.
 *
 * Returns: (type Gtk.MediaFile): a new `GtkMediaFile`
 */

GtkMediaStream *
gtk_media_file_new_for_input_stream (GInputStream *stream)
{
  g_return_val_if_fail (stream == NULL || G_IS_INPUT_STREAM (stream), NULL);

  return g_object_new (gtk_media_file_get_impl_type (),
                       "input-stream", stream,
                       NULL);
}

static gboolean
gtk_media_file_is_open (GtkMediaFile *self)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  return priv->file || priv->input_stream;
}

/**
 * gtk_media_file_clear:
 * @self: a `GtkMediaFile`
 *
 * Resets the media file to be empty.
 */

void
gtk_media_file_clear (GtkMediaFile *self)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_return_if_fail (GTK_IS_MEDIA_FILE (self));

  if (!gtk_media_file_is_open (self))
    return;

  GTK_MEDIA_FILE_GET_CLASS (self)->close (self);

  if (priv->input_stream)
    {
      g_clear_object (&priv->input_stream);
      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INPUT_STREAM]);
    }
  if (priv->file)
    {
      g_clear_object (&priv->file);
      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
    }
}

/**
 * gtk_media_file_set_filename:
 * @self: a `GtkMediaFile`
 * @filename: (type filename) (nullable): name of file to play
 *
 * Sets the `GtkMediaFile` to play the given file.
 *
 * This is a utility function that converts the given @filename
 * to a `GFile` and calls [method@Gtk.MediaFile.set_file].
 **/

void
gtk_media_file_set_filename (GtkMediaFile *self,
                             const char   *filename)
{
  GFile *file;

  g_return_if_fail (GTK_IS_MEDIA_FILE (self));

  if (filename)
    file = g_file_new_for_path (filename);
  else
    file = NULL;

  gtk_media_file_set_file (self, file);

  if (file)
    g_object_unref (file);
}

/**
 * gtk_media_file_set_resource:
 * @self: a `GtkMediaFile`
 * @resource_path: (nullable): path to resource to play
 *
 * Sets the `GtkMediaFile` to play the given resource.
 *
 * This is a utility function that converts the given @resource_path
 * to a `GFile` and calls [method@Gtk.MediaFile.set_file].
 */

void
gtk_media_file_set_resource (GtkMediaFile *self,
                             const char   *resource_path)
{
  GFile *file;

  g_return_if_fail (GTK_IS_MEDIA_FILE (self));

  if (resource_path)
    {
      char *uri, *escaped;

      escaped = g_uri_escape_string (resource_path,
                                     G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE);
      uri = g_strconcat ("resource://", escaped, NULL);
      g_free (escaped);

      file = g_file_new_for_uri (uri);
      g_free (uri);
    }
  else
    {
      file = NULL;
    }


  gtk_media_file_set_file (self, file);

  if (file)
    g_object_unref (file);
}

/**
 * gtk_media_file_set_file:
 * @self: a `GtkMediaFile`
 * @file: (nullable): the file to play
 *
 * Sets the `GtkMediaFile` to play the given file.
 *
 * If any file is still playing, stop playing it.
 */

void
gtk_media_file_set_file (GtkMediaFile *self,
                         GFile        *file)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_return_if_fail (GTK_IS_MEDIA_FILE (self));
  g_return_if_fail (file == NULL || G_IS_FILE (file));

  if (file)
    g_object_ref (file);

  g_object_freeze_notify (G_OBJECT (self));

  gtk_media_file_clear (self);

  if (file)
    {
      priv->file = file;
      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);

      GTK_MEDIA_FILE_GET_CLASS (self)->open (self);
    }

  g_object_thaw_notify (G_OBJECT (self));
}

/**
 * gtk_media_file_get_file:
 * @self: a `GtkMediaFile`
 *
 * Returns the file that @self is currently playing from.
 *
 * When @self is not playing or not playing from a file,
 * %NULL is returned.
 *
 * Returns: (nullable) (transfer none): The currently playing file
 */

GFile *
gtk_media_file_get_file (GtkMediaFile *self)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_return_val_if_fail (GTK_IS_MEDIA_FILE (self), NULL);

  return priv->file;
}

/**
 * gtk_media_file_set_input_stream:
 * @self: a `GtkMediaFile`
 * @stream: (nullable): the stream to play from
 *
 * Sets the `GtkMediaFile` to play the given stream.
 *
 * If anything is still playing, stop playing it.
 *
 * Full control about the @stream is assumed for the duration of
 * playback. The stream will not be closed.
 */

void
gtk_media_file_set_input_stream (GtkMediaFile *self,
                                 GInputStream *stream)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_return_if_fail (GTK_IS_MEDIA_FILE (self));
  g_return_if_fail (stream == NULL || G_IS_INPUT_STREAM (stream));

  if (stream)
    g_object_ref (stream);

  g_object_freeze_notify (G_OBJECT (self));

  gtk_media_file_clear (self);

  if (stream)
    {
      priv->input_stream = stream;
      g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_INPUT_STREAM]);

      GTK_MEDIA_FILE_GET_CLASS (self)->open (self);
    }

  g_object_thaw_notify (G_OBJECT (self));
}

/**
 * gtk_media_file_get_input_stream:
 * @self: a `GtkMediaFile`
 *
 * Returns the stream that @self is currently playing from.
 *
 * When @self is not playing or not playing from a stream,
 * %NULL is returned.
 *
 * Returns: (nullable) (transfer none): The currently playing stream
 */

GInputStream *
gtk_media_file_get_input_stream (GtkMediaFile *self)
{
  GtkMediaFilePrivate *priv = gtk_media_file_get_instance_private (self);

  g_return_val_if_fail (GTK_IS_MEDIA_FILE (self), NULL);

  return priv->input_stream;
}

void
gtk_media_file_extension_init (void)
{
  GIOExtensionPoint *ep;
  GIOModuleScope *scope;
  char **paths;
  int i;

  GTK_DEBUG (MODULES, "Registering extension point %s", GTK_MEDIA_FILE_EXTENSION_POINT_NAME);

  ep = g_io_extension_point_register (GTK_MEDIA_FILE_EXTENSION_POINT_NAME);
  g_io_extension_point_set_required_type (ep, GTK_TYPE_MEDIA_FILE);

  scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);

  paths = _gtk_get_module_path ("media");
  for (i = 0; paths[i]; i++)
    {
      GTK_DEBUG (MODULES, "Scanning io modules in %s", paths[i]);
      g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
    }
  g_strfreev (paths);

  g_io_module_scope_free (scope);

  if (GTK_DEBUG_CHECK (MODULES))
    {
      GList *list, *l;

      list = g_io_extension_point_get_extensions (ep);
      for (l = list; l; l = l->next)
        {
          GIOExtension *ext = l->data;
          g_print ("extension: %s: type %s\n",
                   g_io_extension_get_name (ext),
                   g_type_name (g_io_extension_get_type (ext)));
        }
    }

  /* If the env var is given, check at startup that things actually work */
  if (g_getenv ("GTK_MEDIA"))
    gtk_media_file_get_extension ();
}

Messung V0.5 in Prozent
C=98 H=94 G=95

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-07-03) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.