#ifndef _TimingSystem_h #define _TimingSystem_h /* * subtitle editor * * http://kitone.free.fr/subtitleeditor/ * * Copyright @ 2005-2006, kitone * * Contact: kitone at free dot fr * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This program 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 * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * See gpl.txt for more information regarding the GNU General Public License. * * * \file * \brief * \author kitone (kitone at free dot fr) */ #include #include #include #include "GstLaunch.h" #include "GstMedia.h" #include "WaveformGenerator.h" #include "Waveform.h" #include "SubtitleTime.h" /* * offre une gestion de base pour le rendu sur pixmap * avec des fonctions pour convertir * un point en temps subtitleeditor ou gstreamer ou l'inverse * * le widget garde une taille fixe (sauf redimmension du parent) * pour l'affichage du timing/waveform * ce qui evite d'alloué une enorme zone memoire * quand le fichier (waveform/media) est long * et qu'on applique encore dessus un zoom * ce qui provoque un bug gdk * il y a donc une gestion interne du scroll(bar) */ class DrawingArea : public Gtk::DrawingArea { public: /* * constructeur */ DrawingArea(BaseObjectType* cobject, const Glib::RefPtr& refGlade); /* * */ void set_waveform(Waveform* waveform); /* * le media sur lequel on bosse */ void set_media(GstMedia* media); /* * gestion du zoom (horizontal) * [1, 100] */ void set_zoom(/*guint*/ float zoom); /* * retourne la valeur du zoom */ /*guint */ float get_zoom(); /* * retourne le facteur du zoom [0,1] * 100 / zoom */ float get_zoom_factor(); // 100 / zoom /* * appliquer sur le waveform (vertical) */ void set_scale(float scale); /* * retourne la valeur de scale */ float get_scale(); /* * retourne la position dans l'area par rapport au temps (du waveform) */ int get_pos_by_time(gint64 time); /* * retourne le temps (gstreamer) par rapport a la position (pixel) * sur le waveform */ gint64 get_time_by_pos(gint64 pos); /* * passe d'une position dans l'area a une position dans le channel * channel != len */ int area_2_waveform_channel(int pos); /* * efface le pixmap puis appel Gtk::Widget::queue_draw() */ virtual void force_redraw(); /* * retourne la position du debut de l'affichage * (prise en compte du decalage avec la scrollbar) * return scroll_position */ int get_start_area(); /* * retourne la position de la fin de l'affichage * (prise en compte du decalage avec la scrollbar) * return get_start_area() + width */ int get_end_area(); /* * donne la valeur du HScrollbar * car le widget reste de taille fixe * ce qui evite d'alloué une enorme zone memoire * quand le fichier (waveform/media) est long * et qu'on applique encore dessus un zoom * ce qui provoque un bug gdk */ void set_current_scroll_position(int value); protected: /* * efface simplement le pixmap * afin qu'il soit recrée dans on_expose_event * avec la nouvelle taille */ bool on_configure_event(GdkEventConfigure *ev); /* * dessine le pixmap par rapport a la demande (GdkEventExpose) * si le pixmap n'est pas crée alors il l'est * avec pour taille l'area (ev->area.width) * get_zoom_factor() * * puis il y a un appel a redraw * et enfin on l'affiche grace a Gdk::Window */ bool on_expose_event(GdkEventExpose *ev); /* * virtual pur * il faut redessiner le pixmap */ virtual void redraw() = 0; protected: Waveform* m_waveform; GstMedia* m_media; // valeur du zoom /*guint */float m_zoom; // valeur scale a appliquer au waveform float m_scale; // valeur de la hscrollbar int m_current_scroll_position; }; /* * utilise avec gstreamer pour afficher la video */ class VideoArea : public Gtk::DrawingArea { public: /* * */ VideoArea(BaseObjectType* cobject, const Glib::RefPtr& refGlade); /* * */ ~VideoArea(); /* * */ void set_media(GstMedia* media); /* * connect gstreamer a la Gdk::Window pour afficher la video */ bool on_expose_event(GdkEventExpose *e); /* * */ void draw_text(Gtk::TreeIter it); public: GstMedia* m_media; Glib::RefPtr m_pango_layout; }; /* * */ class TimeDrawingArea : public DrawingArea { public: TimeDrawingArea(BaseObjectType* cobject, const Glib::RefPtr& refGlade); protected: void on_realize(); bool on_expose_event(GdkEventExpose *ev); void redraw(); void draw_sec(gint64 sec, int upper); void draw_time(gint64 sec); protected: Glib::RefPtr m_pango_layout; }; /* * use GDK */ class WaveformDrawingArea : public DrawingArea { public: WaveformDrawingArea(BaseObjectType* cobject, const Glib::RefPtr& refGlade); void set_current_play(gint64 time); protected: void on_realize(); bool on_expose_event(GdkEventExpose *ev); bool on_button_press_event(GdkEventButton *ev); bool on_button_release_event(GdkEventButton *ev); bool on_motion_notify_event(GdkEventMotion *ev); void draw_channel(unsigned int channel, float scale, int y, int height); void draw_markers(); void draw_marker(const Gdk::Color &color, gint64 start, gint64 end); void draw_play_position(); void redraw(); /* * on select un autre subtitle dans la treeview */ void on_subtitle_view_selection_changed(Gtk::TreeIter it); protected: Glib::RefPtr m_gc_play; Gdk::Color m_color_play; Glib::RefPtr m_gc_waveform; Gdk::Color m_color_wave; Glib::RefPtr m_gc_marker; Gdk::Color m_color_marker; Gdk::Color m_color_marker_selected; Gdk::Color m_color_marker_error; // si start > end gint64 m_current_play; }; /* * use CAIRO */ class WaveformDrawingAreaCairo : public DrawingArea { public: WaveformDrawingAreaCairo(BaseObjectType* cobject, const Glib::RefPtr& refGlade); void set_current_play(gint64 time); void force_redraw(); protected: bool on_configure_event(GdkEventConfigure *ev); bool on_expose_event(GdkEventExpose *ev); bool on_motion_notify_event(GdkEventMotion *ev); bool on_button_press_event(GdkEventButton *ev); void on_subtitle_view_selection_changed(Gtk::TreeIter it); void redraw(); cairo_surface_t* update_surface(cairo_surface_t* oldSurface, cairo_t* sourceContext, int x, int y, int width, int height); void draw_channel(cairo_t* drawingContext, unsigned int channel, float max, int y, int height); void draw_play_position(cairo_t* context); void draw_markers(cairo_t* context); void draw_marker(cairo_t* context, gint64 start, gint64 end, float color[4]); protected: gint64 m_current_play; cairo_surface_t* m_waveformSurface; }; /* * */ class TimingSystem : public Gtk::Frame { public: TimingSystem(BaseObjectType* cobject, const Glib::RefPtr& refGlade); ~TimingSystem(); void clear(); /* * media (wav,mp3,divx, ...) or waveform */ bool open_media(const Glib::ustring &uri); /* * */ bool save_waveform(const Glib::ustring &uri); /* * */ void stop(); void play_subtitle(Gtk::TreeIter it); void play_subtitle(const SubtitleTime &start, const SubtitleTime& end); /* * */ Waveform* get_waveform(); protected: void loadCfg(); void saveCfg(); /* * on utilise ça pour demander au drawingarea de ce redessiner par rapport a la taille */ void on_size_allocate(Gtk::Allocation &al); void redraw_area(); void on_spin_zoom_changed(); void on_spin_scale_changed(); void on_signal_setup_view(Glib::ustring mode); void on_signal_subtitle_view_selection_changed(Gtk::TreeIter it); void on_signal_subtitle_time_changed(Gtk::TreeIter it); void on_media_timeout(); void update_view_from_cursor(gint64 time); void on_hscrollbar_value_changed(); void init_hscrollbar(); protected: VideoArea* m_drawingVideo; Waveform* m_waveform; GstMedia* m_media; Gtk::HScrollbar* m_scrollbarWavform; TimeDrawingArea* m_drawingAreaTime; #ifdef ENABLE_CAIRO WaveformDrawingAreaCairo* m_drawingAreaWaveform; #else WaveformDrawingArea* m_drawingAreaWaveform; #endif Gtk::Button* m_buttonPlay; Gtk::Button* m_buttonStop; Gtk::Button* m_buttonPreviousSubtitle; Gtk::Button* m_buttonNextSubtitle; Gtk::Button* m_buttonPlayPreviousSecond; Gtk::Button* m_buttonPlayFirstSecond; Gtk::Button* m_buttonPlayLastSecond; Gtk::Button* m_buttonPlayNextSecond; Gtk::SpinButton* m_spinZoom; Gtk::SpinButton* m_spinScale; Gtk::ToggleButton* m_toggleButtonScroll; sigc::connection m_connection; }; #endif//_TimingSystem_h