/* First, add the boilerplate for the object itself. *Thispartwouldnormallygointheheader.
*/ #define GTK_TYPE_NUCLEAR_MEDIA_STREAM (gtk_nuclear_media_stream_get_type ())
G_DECLARE_FINAL_TYPE (GtkNuclearMediaStream, gtk_nuclear_media_stream, GTK, NUCLEAR_MEDIA_STREAM, GtkMediaStream)
/* Do a full rotation in 5 seconds. * *Wedonotsavestepsherebutrealtimestamps. *GtkMediaStreamusesmicroseconds,sowewilldoso,too.
*/ #define DURATION (5 * G_USEC_PER_SEC)
/* Declare the struct. */ struct _GtkNuclearMediaStream
{ /* We now inherit from the media stream object. */
GtkMediaStream parent_instance;
/* This variable stores the progress of our video.
*/
gint64 progress;
/* This variable stores the timestamp of the last *timeweupdatedtheprogressvariablewhenthe *videoiscurrentlyplaying. *Thisissothatwecanalwaysaccuratelycomputethe *progresswe'vehad,evenifthetimeoutdoesnot *exactlywork.
*/
gint64 last_time;
/* This variable again holds the ID of the timer that *updatesourprogressvariable.Nothingchangesabout *howthisworkscomparedtothepreviousexample.
*/
guint source_id;
};
/* GtkMediaStream is a GdkPaintable. So when we want to display video, *wehavetoimplementtheinterface,justlikeintheanimationexample.
*/ staticvoid
gtk_nuclear_media_stream_snapshot (GdkPaintable *paintable,
GdkSnapshot *snapshot, double width, double height)
{
GtkNuclearMediaStream *nuclear = GTK_NUCLEAR_MEDIA_STREAM (paintable);
/* We call the function from the previous example here. */
gtk_nuclear_snapshot (snapshot,
&(GdkRGBA) { 0, 0, 0, 1 }, /* black */
&(GdkRGBA) { 0.9, 0.75, 0.15, 1.0 }, /* yellow */
width, height, 360 * nuclear->progress / DURATION);
}
/* Same thing as with the animation */ return gtk_nuclear_icon_new (360 * nuclear->progress / DURATION);
}
static GdkPaintableFlags
gtk_nuclear_media_stream_get_flags (GdkPaintable *paintable)
{ /* And same thing as with the animation over here, too. */ return GDK_PAINTABLE_STATIC_SIZE;
}
/* This time, we inherit from GTK_TYPE_MEDIA_STREAM */
G_DEFINE_TYPE_WITH_CODE (GtkNuclearMediaStream, gtk_nuclear_media_stream, GTK_TYPE_MEDIA_STREAM,
G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
gtk_nuclear_media_stream_paintable_init))
/* Compute the time that has elapsed since the last time we were called *andaddittoourcurrentprogress.
*/
current_time = g_source_get_time (g_main_current_source ());
nuclear->progress += current_time - nuclear->last_time;
/* Check if we've ended */ if (nuclear->progress > DURATION)
{ if (gtk_media_stream_get_loop (GTK_MEDIA_STREAM (nuclear)))
{ /* We're looping. So make the progress loop using modulo */
nuclear->progress %= DURATION;
} else
{ /* Just make sure we don't overflow */
nuclear->progress = DURATION;
}
}
/* Update the last time to the current timestamp. */
nuclear->last_time = current_time;
/* Update the timestamp of the media stream */
gtk_media_stream_update (GTK_MEDIA_STREAM (nuclear), nuclear->progress);
/* We also need to invalidate our contents again. *Afterall,weareavideoandnotjustanaudiostream.
*/
gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
/* Now check if we have finished playing and if so, *tellthemediastream.Themediastreamwillthen *callourpausefunctiontopausethestream.
*/ if (nuclear->progress >= DURATION)
gtk_media_stream_stream_ended (GTK_MEDIA_STREAM (nuclear));
/* The timeout function is removed by the pause function, *sowecanjustalwaysreturnthisvalue.
*/ return G_SOURCE_CONTINUE;
}
/* This function will be called when a playing stream *getspaused. *Soweremovetheupdatingsourcehereandsetit *backto0sothatthefinalizefunctiondoesn'ttry *toremoveitagain.
*/
g_clear_handle_id (&nuclear->source_id, g_source_remove);
nuclear->last_time = 0;
}
/* This is optional functionality for media streams, *butnotbeingabletoseekiskindaboring. *Andit'strivialtoimplement,solet'sgoforit.
*/
nuclear->progress = timestamp;
/* Media streams are asynchronous, so seeking can take a while. *Wehoweverdon'tneedthatfunctionality,sowecanjust *reportsuccess.
*/
gtk_media_stream_seek_success (stream);
/* We also have to update our timestamp and tell the *paintableinterfaceabouttheseek
*/
gtk_media_stream_update (stream, nuclear->progress);
gdk_paintable_invalidate_contents (GDK_PAINTABLE (nuclear));
}
/* Again, we need to implement the finalize function.
*/ staticvoid
gtk_nuclear_media_stream_finalize (GObject *object)
{
GtkNuclearMediaStream *nuclear = GTK_NUCLEAR_MEDIA_STREAM (object);
/* This time, we need to check if the source exists before *removingitasitonlyexistswhileweareplaying.
*/ if (nuclear->source_id > 0)
g_source_remove (nuclear->source_id);
/* Don't forget to chain up to the parent class' implementation *ofthefinalizefunction.
*/
G_OBJECT_CLASS (gtk_nuclear_media_stream_parent_class)->finalize (object);
}
/* In the class declaration, we need to implement the media stream */ staticvoid
gtk_nuclear_media_stream_class_init (GtkNuclearMediaStreamClass *klass)
{
GtkMediaStreamClass *stream_class = GTK_MEDIA_STREAM_CLASS (klass);
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
staticvoid
gtk_nuclear_media_stream_init (GtkNuclearMediaStream *nuclear)
{ /* This time, we don't have to add a timer here, because media *streamsstartpaused. * *However,mediastreamsneedtotellGTKoncetheyareinitialized, *sowedothathere.
*/
gtk_media_stream_stream_prepared (GTK_MEDIA_STREAM (nuclear), FALSE, TRUE, TRUE,
DURATION);
}
/* And finally, we add the simple constructor we declared in the header. */
GtkMediaStream *
gtk_nuclear_media_stream_new (void)
{ return g_object_new (GTK_TYPE_NUCLEAR_MEDIA_STREAM, NULL);
}
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.