From a560b5c94f7f7945dbbd03935c89738e62371e04 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Tue, 3 Sep 2013 22:03:19 +0200 Subject: preview: extract preview area as separate widget --- src/Makefile.am | 3 +- src/mi-info.vala | 89 +++++++++---------------------------- src/mi-preview.vala | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 68 deletions(-) create mode 100644 src/mi-preview.vala diff --git a/src/Makefile.am b/src/Makefile.am index fe7489e..e370d7b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,8 @@ VALAFLAGS = \ gst_mi_SOURCES = \ mi.vala \ mi-app.vala \ - mi-info.vala + mi-info.vala \ + mi-preview.vala gst_mi_LDADD = \ $(MI_LIBS) -lgstinterfaces-0.10 -lgstpbutils-0.10 diff --git a/src/mi-info.vala b/src/mi-info.vala index 8291b95..a304042 100644 --- a/src/mi-info.vala +++ b/src/mi-info.vala @@ -57,8 +57,7 @@ public class MediaInfo.Info : Box private Notebook video_streams; // depending on screen resolution private Notebook audio_streams; private Notebook subtitle_streams; - private AspectFrame drawing_frame; - private DrawingArea drawing_area; + private Preview preview; private ScrolledWindow info_area; // gstreamer objects private Discoverer dc; @@ -67,7 +66,6 @@ public class MediaInfo.Info : Box private uint num_video_streams; private uint num_audio_streams; private uint num_subtitle_streams; - private float video_ratio = 1.0f; private ArrayList video_resolutions = null; // stream data private Gdk.Pixbuf album_art = null; @@ -168,19 +166,9 @@ public class MediaInfo.Info : Box } // add widgets - drawing_frame = new AspectFrame (null, 0.5f, 0.5f, 1.25f, false); - drawing_frame.set_size_request (160, 128); - drawing_frame.set_shadow_type (Gtk.ShadowType.NONE); - - pack_start (drawing_frame, true, true, 0); - - drawing_area = new DrawingArea (); - drawing_area.set_size_request (160, 128); - drawing_area.draw.connect (on_drawing_area_draw); - drawing_area.size_allocate.connect (on_drawing_area_size_allocate); - drawing_area.realize.connect (on_drawing_area_realize); - drawing_area.unrealize.connect (on_drawing_area_unrealize); - drawing_frame.add (drawing_area); + preview = new Preview (); + preview.draw.connect (on_preview_draw); + pack_start (preview, false, false, 0); info_area = new ScrolledWindow (null, null); info_area.set_policy (PolicyType.NEVER, PolicyType.ALWAYS); @@ -324,7 +312,6 @@ public class MediaInfo.Info : Box // stop previous playback pb.set_state (State.READY); album_art = null; - drawing_area.queue_draw(); try { FileInfo finfo = file.query_info ("standard::*", FileQueryInfoFlags.NONE, null); @@ -736,19 +723,12 @@ public class MediaInfo.Info : Box if (have_video) { Gdk.Point res = video_resolutions[0]; - video_ratio = (float)(res.x) / (float)(res.y); - debug ("video_ratio from video: %f", video_ratio); + preview.set_content_size(res.x, res.y); } else if (album_art != null) { - int sw=album_art.get_width (); - int sh=album_art.get_height (); - video_ratio = (float)sw / (float)sh; - debug ("video_ratio from album art: %f", video_ratio); + preview.set_static_content(album_art); } else { - video_ratio = 1.0f; - debug ("video_ratio --- : %f", video_ratio); + preview.reset(); } - drawing_frame.set (0.5f, 0.5f, video_ratio, false); - drawing_area.queue_resize(); //l = info.get_container_streams (); @@ -759,7 +739,8 @@ public class MediaInfo.Info : Box // signal handlers - private void on_drawing_area_size_allocate (Widget widget, Gtk.Allocation frame) + /* + private void on_size_allocate (Widget widget, Gtk.Allocation box) { Gtk.Allocation alloc; get_allocation (out alloc); @@ -768,57 +749,29 @@ public class MediaInfo.Info : Box Gtk.Requisition requisition; info_area.get_child ().get_preferred_size (null, out requisition); debug ("info_area: %d x %d", requisition.width, requisition.height); - debug ("video_area: %d x %d", frame.width, frame.height); + int frame_height = (int)(box.width / video_ratio); + debug ("video_area: %d x %d", box.width, frame_height); - int max_h = alloc.height - frame.height; + int max_h = alloc.height - frame_height; info_area.set_min_content_height (int.min (requisition.height, max_h)); } + */ - private bool on_drawing_area_draw (Widget widget, Cairo.Context cr) + private bool on_preview_draw (Widget widget, Cairo.Context cr) { - // redraw if not playing and if there is no video if (pb.current_state < State.PAUSED || !have_video) { widget.set_double_buffered (true); - - Gtk.Allocation frame; - widget.get_allocation (out frame); - int w = frame.width; - int h = frame.height; - //debug ("on_drawing_area_draw:video_ratio: %d x %d : %f", w, h, video_ratio); - - if (album_art != null) { - Gdk.Pixbuf pb = album_art.scale_simple (w, h, Gdk.InterpType.BILINEAR); - Gdk.cairo_set_source_pixbuf (cr, pb, 0, 0); - } else { - cr.set_source_rgb (0, 0, 0); - } - cr.rectangle (0, 0, w, h); - cr.fill (); } else { widget.set_double_buffered (false); } return false; } - - private void on_drawing_area_realize (Widget widget) - { - widget.get_window ().ensure_native (); - widget.set_double_buffered (false); - } - - private void on_drawing_area_unrealize (Widget widget) - { - pb.set_state (State.NULL); - } private void on_element_sync_message (Gst.Bus bus, Message message) { if (Gst.Video.is_video_overlay_prepare_window_handle_message (message)) { Gst.Video.Overlay overlay = message.src as Gst.Video.Overlay; - overlay.set_window_handle ((uint *)Gdk.X11Window.get_xid (drawing_area.get_window())); - drawing_frame.set (0.5f, 0.5f, video_ratio, false); - debug ("on_element_sync_message:video_ratio: %f", video_ratio); - drawing_area.queue_resize(); + overlay.set_window_handle ((uint *)Gdk.X11Window.get_xid (preview.get_window ())); /* playbin does this in 1.0 if (message.src.get_class ().find_property ("force-aspect-ratio") != null) { @@ -833,7 +786,12 @@ public class MediaInfo.Info : Box * - we can use: * - pad.get_stream_id() on playbin * - sinfo.get_stream_id() on discoverer - * + * - gather all stream-ids and build {audio,video,subtitle}_stream_map with + * stream-id as a key and value initially set to -1 + * - have cur_{audio,video,subtile} = 0 + * - listen for playbin.pad_added and set the stream_id to cur_* + * - ideally playbin will have api to switch to a stream-by-id + * - or we sort the discoverer streams by stream-info too */ private void on_video_stream_switched (Notebook nb, Widget page, uint page_num) { @@ -841,10 +799,7 @@ public class MediaInfo.Info : Box debug ("Switching video to: %u", page_num); ((GLib.Object)pb).set_property ("current-video", (int)page_num); Gdk.Point res = video_resolutions[(int)page_num]; - video_ratio = (float)(res.x) / (float)(res.y); - drawing_frame.set (0.5f, 0.5f, video_ratio, false); - drawing_area.queue_resize(); - debug ("on_video_stream_switched:video_ratio: %f", video_ratio); + preview.set_content_size(res.x, res.y); } } diff --git a/src/mi-preview.vala b/src/mi-preview.vala new file mode 100644 index 0000000..48ce6af --- /dev/null +++ b/src/mi-preview.vala @@ -0,0 +1,125 @@ +/* GStreamer media browser + * Copyright (C) 2010-2013 Stefan Sauer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Steet, + * Boston, MA 02110-1301, USA. + */ + +using Gtk; + +public class MediaInfo.Preview : DrawingArea { + private Gdk.Pixbuf content = null; + private int width = 0; + private int height = 0; + private float ratio = 0.0f; + private int alloc_width; + private int alloc_height; + + construct { + set_has_window (true); + } + + public void reset () { + content = null; + ratio = 0.0f; + debug ("no content: 0.0"); + queue_resize (); + } + + public void set_static_content (Gdk.Pixbuf? content) { + this.content = content; + if (content != null) { + width = content.get_width (); + height = content.get_height (); + ratio = (float)width / (float)height; + debug ("ratio from album art: %f", ratio); + queue_resize (); + } + } + + public void set_content_size (uint width, uint height) { + if (height != 0) { + ratio = (float)width / (float)height; + } else { + ratio = 0.0f; + } + debug ("ratio from video: %f", ratio); + queue_resize (); + } + + // vmethods + + public override SizeRequestMode get_request_mode () { + return SizeRequestMode.HEIGHT_FOR_WIDTH; + } + + public override void get_preferred_width (out int minimal_width, out int natural_width) { + if (ratio != 0.0) { + minimal_width = natural_width = (int)(alloc_height * ratio); + } else { + minimal_width = natural_width = 0; + } + debug ("width w,h: %d,%d", natural_width, alloc_height); + } + + public override void get_preferred_height (out int minimal_height, out int natural_height) { + if (ratio != 0.0) { + minimal_height = natural_height = (int)(alloc_width / ratio); + } else { + minimal_height = natural_height = 0; + } + debug ("height w,h: %d,%d", alloc_width, natural_height); + } + + public override void get_preferred_width_for_height (int height, out int minimal_width, out int natural_width) { + if (ratio != 0.0) { + minimal_width = natural_width = (int)(height * ratio); + } else { + minimal_width = natural_width = 0; + } + debug ("width_for_height w,h: %d,%d", natural_width, height); + } + + public override void get_preferred_height_for_width (int width, out int minimal_height, out int natural_height) { + if (ratio != 0.0) { + minimal_height = natural_height = (int)(width / ratio); + } else { + minimal_height = natural_height = 0; + } + debug ("height_for_width w,h: %d,%d", width, natural_height); + } + + public override void size_allocate (Gtk.Allocation alloc) { + base.size_allocate (alloc); + + alloc_width = alloc.width; + alloc_height = alloc.height; + debug ("alloc w,h: %d,%d", alloc_width, alloc_height); + } + + public override bool draw (Cairo.Context cr) { + if (content != null) { + Gdk.Pixbuf pb = content.scale_simple (alloc_width, alloc_height, Gdk.InterpType.BILINEAR); + Gdk.cairo_set_source_pixbuf (cr, pb, 0, 0); + } else { + cr.set_source_rgb (0, 0, 0); + } + cr.rectangle (0, 0, alloc_width, alloc_height); + cr.fill (); + debug ("draw w,h: %d,%d", alloc_width, alloc_height); + return false; + } +} + -- cgit v1.2.3