1 // -------------------------------------------------------------------------
4 // Author: Guilhem Lavaux
7 // Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
8 // License: wxWindows license
9 // -------------------------------------------------------------------------
12 #pragma implementation "vidxanm.h"
15 #include <wx/wxprec.h>
22 #include <wx/gtk/win_gtk.h>
25 #include <X11/Intrinsic.h>
27 #include <gtk/gtkwidget.h>
28 #include <gtk/gtkwindow.h>
30 #include <gdk/gdkprivate.h>
33 #include <wx/filefn.h>
34 #include <wx/wfstream.h>
35 #include <wx/datstrm.h>
36 #include <wx/tokenzr.h>
38 #define WXMMEDIA_INTERNAL
39 #include "wx/mmedia/vidbase.h"
40 #include "wx/mmedia/vidxanm.h"
42 IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM
, wxVideoBaseDriver
)
44 // -------------------------------------------------------------------------
45 // End process detector
47 class wxVideoXANIMProcess
: public wxProcess
{
49 wxVideoXANIMProcess(wxVideoXANIM
*xanim
);
51 void OnTerminate(int pid
, int status
);
54 wxVideoXANIM
*m_vid_xanim
;
57 class wxVideoXANIMOutput
: public wxProcess
{
61 void OnTerminate(int pid
, int status
);
63 bool IsTerminated() const;
68 // -------------------------------------------------------------------------
69 // XAnim video driver (process handling implementation)
71 wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM
*xanim
)
76 void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid
), int WXUNUSED(status
))
78 m_vid_xanim
->m_xanim_started
= FALSE
;
79 m_vid_xanim
->OnFinished();
82 wxVideoXANIMOutput::wxVideoXANIMOutput()
89 bool wxVideoXANIMOutput::IsTerminated() const
94 void wxVideoXANIMOutput::OnTerminate(int pid
, int status
)
99 // -------------------------------------------------------------------------
100 // XAnim video driver (implementation)
102 wxVideoXANIM::wxVideoXANIM()
103 : wxVideoBaseDriver()
105 m_internal
= new wxXANIMinternal
;
106 m_xanim_detector
= new wxVideoXANIMProcess(this);
107 m_xanim_started
= FALSE
;
110 m_remove_file
= FALSE
;
113 wxVideoXANIM::wxVideoXANIM(wxInputStream
& str
)
114 : wxVideoBaseDriver(str
)
116 m_internal
= new wxXANIMinternal
;
117 m_xanim_detector
= new wxVideoXANIMProcess(this);
118 m_xanim_started
= FALSE
;
123 m_filename
= wxGetTempFileName("vidxa");
124 m_remove_file
= TRUE
;
125 wxFileOutputStream
fout(m_filename
);
132 wxVideoXANIM::wxVideoXANIM(const wxString
& filename
)
134 m_internal
= new wxXANIMinternal
;
135 m_xanim_detector
= new wxVideoXANIMProcess(this);
136 m_xanim_started
= FALSE
;
139 m_filename
= filename
;
140 m_remove_file
= FALSE
;
147 wxVideoXANIM::~wxVideoXANIM()
152 delete m_xanim_detector
;
155 wxRemoveFile(m_filename
);
158 // -------------------------------------------------------------------------
161 bool wxVideoXANIM::Play()
163 if (!m_paused
&& m_xanim_started
)
165 if (!m_video_output
) {
166 wxVideoCreateFrame(this);
170 // The movie starts with xanim
171 if (RestartXANIM()) {
178 bool wxVideoXANIM::Pause()
180 if (!m_paused
&& SendCommand(" ")) {
187 bool wxVideoXANIM::Resume()
189 if (m_paused
&& SendCommand(" ")) {
196 bool wxVideoXANIM::Stop()
198 if (!m_xanim_started
)
203 // We are waiting for the termination of the subprocess.
204 while (m_xanim_started
) {
213 // -------------------------------------------------------------------------
214 // Movie size controller
216 bool wxVideoXANIM::SetSize(wxSize size
)
221 m_video_output
->SetSize(size
.GetWidth(), size
.GetHeight());
225 bool wxVideoXANIM::GetSize(wxSize
& size
) const
229 size
.Set(m_size
[0], m_size
[1]);
233 // -------------------------------------------------------------------------
234 // Capabilities of XAnim
236 bool wxVideoXANIM::IsCapable(wxVideoType v_type
) const
238 if (v_type
== wxVIDEO_MSAVI
|| v_type
== wxVIDEO_MPEG
||
239 v_type
== wxVIDEO_QT
|| v_type
== wxVIDEO_GIF
|| v_type
== wxVIDEO_JMOV
||
240 v_type
== wxVIDEO_FLI
|| v_type
== wxVIDEO_IFF
|| v_type
== wxVIDEO_SGI
)
246 // -------------------------------------------------------------------------
249 wxString
wxVideoXANIM::GetMovieCodec() const
256 wxString
wxVideoXANIM::GetAudioCodec() const
263 wxUint32
wxVideoXANIM::GetSampleRate() const
270 wxUint8
wxVideoXANIM::GetChannels() const
277 wxUint8
wxVideoXANIM::GetBPS() const
284 double wxVideoXANIM::GetFrameRate() const
291 wxUint32
wxVideoXANIM::GetNbFrames() const
299 bool wxVideoXANIM::IsPaused() const
304 bool wxVideoXANIM::IsStopped() const
306 return !m_xanim_started
;
309 // -------------------------------------------------------------------------
312 bool wxVideoXANIM::AttachOutput(wxWindow
& out
)
314 if (!wxVideoBaseDriver::AttachOutput(out
))
320 void wxVideoXANIM::DetachOutput()
323 m_xanim_started
= FALSE
;
326 wxVideoBaseDriver::DetachOutput();
329 // -------------------------------------------------------------------------
330 // Lowlevel XAnim controller
332 bool wxVideoXANIM::SendCommand(const char *command
, char **ret
,
335 if (!m_xanim_started
)
339 // Send a command to XAnim through X11 Property
340 XChangeProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
341 m_internal
->xanim_atom
,
342 XA_STRING
, 8, PropModeReplace
, (unsigned char *)command
,
344 XFlush(m_internal
->xanim_dpy
);
350 XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
351 m_internal
->xanim_ret
, 0, 16, True
, AnyPropertyType
,
352 &prop_type
, &prop_format
, (unsigned long *)size
,
353 &extra
, (unsigned char **)ret
);
358 bool wxVideoXANIM::CollectInfo()
360 wxVideoXANIMOutput
*xanimProcess
;
361 wxString xanim_command
;
362 wxStringTokenizer tokenizer
;
364 xanimProcess
= new wxVideoXANIMOutput
;
365 xanim_command
= wxT("xanim +v +Zv -Ae ");
366 xanim_command
+= m_filename
;
367 if (!wxExecute(xanim_command
, FALSE
, xanimProcess
))
370 wxInputStream
*infoStream
= xanimProcess
->GetInputStream();
371 wxString totalOutput
;
373 while (infoStream
->LastError() == wxSTREAM_NOERROR
) {
376 infoStream
->Read(line
, sizeof(line
)-1);
377 if (infoStream
->LastRead() == 0)
380 line
[infoStream
->LastRead()] = 0;
385 // This is good for everything ... :-)
386 int position
= totalOutput
.Find(wxT("Video Codec:"));
388 totalOutput
.Remove(0, position
+13);
390 position
= totalOutput
.Find(wxT("depth="));
391 m_movieCodec
= totalOutput(0, position
);
393 totalOutput
.Remove(0, position
);
394 tokenizer
.SetString(totalOutput
, "\n\r");
396 // the rest of the line
397 wxString token
= tokenizer
.GetNextToken();
398 unsigned long my_long
;
401 totalOutput.ToULong(&my_long); \
405 totalOutput
= tokenizer
.GetString();
406 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
408 position
= totalOutput
.Find(wxT("Rate"));
409 m_audioCodec
= totalOutput(0, position
-1);
412 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
413 GETINT(m_sampleRate
);
415 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
418 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
421 tokenizer
.Reinit(totalOutput
);
422 tokenizer
.GetNextToken();
423 totalOutput
= tokenizer
.GetString();
424 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
426 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
429 totalOutput
.Remove(0,1);
432 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
435 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
436 totalOutput
.ToDouble(&m_frameRate
);
438 // We wait for the conclusion
439 while (!xanimProcess
->IsTerminated())
447 bool wxVideoXANIM::RestartXANIM()
449 wxString xanim_command
;
453 unsigned long nitems
;
458 if (!m_video_output
|| m_xanim_started
)
461 // Check if we can change the size of the window dynamicly
462 xanim_chg_size
= TRUE
;
463 // Get current display
465 m_internal
->xanim_dpy
= gdk_display
;
466 GtkPizza
*pizza
= GTK_PIZZA( m_video_output
->m_wxwindow
);
467 GdkWindow
*window
= pizza
->bin_window
;
469 m_internal
->xanim_window
=
470 ((GdkWindowPrivate
*)window
)->xwindow
;
472 // Get the XANIM atom
473 m_internal
->xanim_atom
= XInternAtom(m_internal
->xanim_dpy
,
474 "XANIM_PROPERTY", False
);
477 xanim_command
.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
478 "+Av70 %s %s"), m_internal
->xanim_window
,
479 (xanim_chg_size
) ? _T("") : _T(""),
480 WXSTRINGCAST m_filename
);
483 if (!wxExecute(xanim_command
, FALSE
, m_xanim_detector
))
486 // Wait for XAnim to be ready
488 m_xanim_started
= TRUE
;
489 while (nitems
== 0 && m_xanim_started
) {
490 ret
= XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
491 m_internal
->xanim_atom
,
492 0, 4, False
, AnyPropertyType
, &prop_type
,
493 &prop_format
, &nitems
, &extra
,
494 (unsigned char **)&prop
);
500 vibrato_size
= m_video_output
->GetSize();
502 vibrato_size
.SetWidth(vibrato_size
.GetWidth()+1);
503 m_video_output
->SetSize(vibrato_size
);
504 vibrato_size
.SetWidth(vibrato_size
.GetWidth()-1);
505 m_video_output
->SetSize(vibrato_size
);
506 // Very useful ! Actually it sends a SETSIZE event to XAnim