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
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()
83 : wxProcess(NULL
, TRUE
, -1)
88 bool wxVideoXANIMOutput::IsTerminated() const
93 void wxVideoXANIMOutput::OnTerminate(int pid
, int status
)
98 // -------------------------------------------------------------------------
99 // XAnim video driver (implementation)
101 wxVideoXANIM::wxVideoXANIM()
102 : wxVideoBaseDriver()
104 m_internal
= new wxXANIMinternal
;
105 m_xanim_detector
= new wxVideoXANIMProcess(this);
106 m_xanim_started
= FALSE
;
109 m_remove_file
= FALSE
;
112 wxVideoXANIM::wxVideoXANIM(wxInputStream
& str
)
113 : wxVideoBaseDriver(str
)
115 m_internal
= new wxXANIMinternal
;
116 m_xanim_detector
= new wxVideoXANIMProcess(this);
117 m_xanim_started
= FALSE
;
122 m_filename
= wxGetTempFileName("vidxa");
123 m_remove_file
= TRUE
;
124 wxFileOutputStream
fout(m_filename
);
131 wxVideoXANIM::wxVideoXANIM(const wxString
& filename
)
133 m_internal
= new wxXANIMinternal
;
134 m_xanim_detector
= new wxVideoXANIMProcess(this);
135 m_xanim_started
= FALSE
;
138 m_filename
= filename
;
139 m_remove_file
= FALSE
;
146 wxVideoXANIM::~wxVideoXANIM()
151 delete m_xanim_detector
;
154 wxRemoveFile(m_filename
);
157 // -------------------------------------------------------------------------
160 bool wxVideoXANIM::Play()
162 if (!m_paused
&& m_xanim_started
)
164 if (!m_video_output
) {
165 wxVideoCreateFrame(this);
169 // The movie starts with xanim
170 if (RestartXANIM()) {
177 bool wxVideoXANIM::Pause()
179 if (!m_paused
&& SendCommand(" ")) {
186 bool wxVideoXANIM::Resume()
188 if (m_paused
&& SendCommand(" ")) {
195 bool wxVideoXANIM::Stop()
197 if (!m_xanim_started
)
202 // We are waiting for the termination of the subprocess.
203 while (m_xanim_started
) {
212 // -------------------------------------------------------------------------
213 // Movie size controller
215 bool wxVideoXANIM::SetSize(wxSize size
)
220 m_video_output
->SetSize(size
.GetWidth(), size
.GetHeight());
224 bool wxVideoXANIM::GetSize(wxSize
& size
) const
228 size
.Set(m_size
[0], m_size
[1]);
232 // -------------------------------------------------------------------------
233 // Capabilities of XAnim
235 bool wxVideoXANIM::IsCapable(wxVideoType v_type
) const
237 if (v_type
== wxVIDEO_MSAVI
|| v_type
== wxVIDEO_MPEG
||
238 v_type
== wxVIDEO_QT
|| v_type
== wxVIDEO_GIF
|| v_type
== wxVIDEO_JMOV
||
239 v_type
== wxVIDEO_FLI
|| v_type
== wxVIDEO_IFF
|| v_type
== wxVIDEO_SGI
)
245 // -------------------------------------------------------------------------
248 wxString
wxVideoXANIM::GetMovieCodec() const
255 wxString
wxVideoXANIM::GetAudioCodec() const
262 wxUint32
wxVideoXANIM::GetSampleRate() const
269 wxUint8
wxVideoXANIM::GetChannels() const
276 wxUint8
wxVideoXANIM::GetBPS() const
283 double wxVideoXANIM::GetFrameRate() const
290 wxUint32
wxVideoXANIM::GetNbFrames() const
298 bool wxVideoXANIM::IsPaused() const
303 bool wxVideoXANIM::IsStopped() const
305 return !m_xanim_started
;
308 // -------------------------------------------------------------------------
311 bool wxVideoXANIM::AttachOutput(wxWindow
& out
)
313 if (!wxVideoBaseDriver::AttachOutput(out
))
319 void wxVideoXANIM::DetachOutput()
322 m_xanim_started
= FALSE
;
325 wxVideoBaseDriver::DetachOutput();
328 // -------------------------------------------------------------------------
329 // Lowlevel XAnim controller
331 bool wxVideoXANIM::SendCommand(const char *command
, char **ret
,
334 if (!m_xanim_started
)
338 // Send a command to XAnim through X11 Property
339 XChangeProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
340 m_internal
->xanim_atom
,
341 XA_STRING
, 8, PropModeReplace
, (unsigned char *)command
,
343 XFlush(m_internal
->xanim_dpy
);
349 XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
350 m_internal
->xanim_ret
, 0, 16, True
, AnyPropertyType
,
351 &prop_type
, &prop_format
, (unsigned long *)size
,
352 &extra
, (unsigned char **)ret
);
357 bool wxVideoXANIM::CollectInfo()
359 wxVideoXANIMOutput
*xanimProcess
;
360 wxString xanim_command
;
361 wxStringTokenizer tokenizer
;
363 xanimProcess
= new wxVideoXANIMOutput
;
364 xanim_command
= wxT("xanim +v +Zv -Ae ");
365 xanim_command
+= m_filename
;
366 if (!wxExecute(xanim_command
, FALSE
, xanimProcess
))
369 wxInputStream
*infoStream
= xanimProcess
->GetInputStream();
370 wxString totalOutput
;
372 while (infoStream
->LastError() == wxSTREAM_NOERROR
) {
375 infoStream
->Read(line
, sizeof(line
)-1);
376 if (infoStream
->LastRead() == 0)
379 line
[infoStream
->LastRead()] = 0;
384 // This is good for everything ... :-)
385 int position
= totalOutput
.Find(wxT("Video Codec:"));
387 totalOutput
.Remove(0, position
+13);
389 position
= totalOutput
.Find(wxT("depth="));
390 m_movieCodec
= totalOutput(0, position
);
392 totalOutput
.Remove(0, position
);
393 tokenizer
.SetString(totalOutput
, "\n\r");
395 // the rest of the line
396 wxString token
= tokenizer
.GetNextToken();
397 unsigned long my_long
;
400 totalOutput.ToULong(&my_long); \
404 totalOutput
= tokenizer
.GetString();
405 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
407 position
= totalOutput
.Find(wxT("Rate"));
408 m_audioCodec
= totalOutput(0, position
-1);
411 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
412 GETINT(m_sampleRate
);
414 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
417 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
420 tokenizer
.Reinit(totalOutput
);
421 tokenizer
.GetNextToken();
422 totalOutput
= tokenizer
.GetString();
423 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
425 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
428 totalOutput
.Remove(0,1);
431 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
434 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
435 totalOutput
.ToDouble(&m_frameRate
);
437 // We wait for the conclusion
438 while (!xanimProcess
->IsTerminated())
446 bool wxVideoXANIM::RestartXANIM()
448 wxString xanim_command
;
452 unsigned long nitems
;
457 if (!m_video_output
|| m_xanim_started
)
460 // Check if we can change the size of the window dynamicly
461 xanim_chg_size
= TRUE
;
462 // Get current display
464 m_internal
->xanim_dpy
= gdk_display
;
465 GtkPizza
*pizza
= GTK_PIZZA( m_video_output
->m_wxwindow
);
466 GdkWindow
*window
= pizza
->bin_window
;
468 m_internal
->xanim_window
=
469 ((GdkWindowPrivate
*)window
)->xwindow
;
471 // Get the XANIM atom
472 m_internal
->xanim_atom
= XInternAtom(m_internal
->xanim_dpy
,
473 "XANIM_PROPERTY", False
);
476 xanim_command
.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
477 "+Av70 %s %s"), m_internal
->xanim_window
,
478 (xanim_chg_size
) ? _T("") : _T(""),
479 WXSTRINGCAST m_filename
);
482 if (!wxExecute(xanim_command
, FALSE
, m_xanim_detector
))
485 // Wait for XAnim to be ready
487 m_xanim_started
= TRUE
;
488 while (nitems
== 0 && m_xanim_started
) {
489 ret
= XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
490 m_internal
->xanim_atom
,
491 0, 4, False
, AnyPropertyType
, &prop_type
,
492 &prop_format
, &nitems
, &extra
,
493 (unsigned char **)&prop
);
499 vibrato_size
= m_video_output
->GetSize();
501 vibrato_size
.SetWidth(vibrato_size
.GetWidth()+1);
502 m_video_output
->SetSize(vibrato_size
);
503 vibrato_size
.SetWidth(vibrato_size
.GetWidth()-1);
504 m_video_output
->SetSize(vibrato_size
);
505 // Very useful ! Actually it sends a SETSIZE event to XAnim