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"
23 #include <wx/gtk/win_gtk.h>
27 #include <X11/Intrinsic.h>
29 #include <gtk/gtkwidget.h>
30 #include <gtk/gtkwindow.h>
32 #include <gdk/gdkprivate.h>
35 #include <wx/filefn.h>
36 #include <wx/wfstream.h>
37 #include <wx/datstrm.h>
38 #include <wx/tokenzr.h>
40 #define WXMMEDIA_INTERNAL
41 #include "wx/mmedia/vidbase.h"
42 #include "wx/mmedia/vidxanm.h"
44 IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM
, wxVideoBaseDriver
)
46 // -------------------------------------------------------------------------
47 // End process detector
49 class wxVideoXANIMProcess
: public wxProcess
{
51 wxVideoXANIMProcess(wxVideoXANIM
*xanim
);
53 void OnTerminate(int pid
, int status
);
56 wxVideoXANIM
*m_vid_xanim
;
59 class wxVideoXANIMOutput
: public wxProcess
{
63 void OnTerminate(int pid
, int status
);
65 bool IsTerminated() const;
70 // -------------------------------------------------------------------------
71 // XAnim video driver (process handling implementation)
73 wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM
*xanim
)
78 void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid
), int WXUNUSED(status
))
80 m_vid_xanim
->m_xanim_started
= FALSE
;
81 m_vid_xanim
->OnFinished();
84 wxVideoXANIMOutput::wxVideoXANIMOutput()
91 bool wxVideoXANIMOutput::IsTerminated() const
96 void wxVideoXANIMOutput::OnTerminate(int pid
, int status
)
101 // -------------------------------------------------------------------------
102 // XAnim video driver (implementation)
104 wxVideoXANIM::wxVideoXANIM()
105 : wxVideoBaseDriver()
107 m_internal
= new wxXANIMinternal
;
108 m_xanim_detector
= new wxVideoXANIMProcess(this);
109 m_xanim_started
= FALSE
;
112 m_remove_file
= FALSE
;
115 wxVideoXANIM::wxVideoXANIM(wxInputStream
& str
)
116 : wxVideoBaseDriver(str
)
118 m_internal
= new wxXANIMinternal
;
119 m_xanim_detector
= new wxVideoXANIMProcess(this);
120 m_xanim_started
= FALSE
;
125 m_filename
= wxGetTempFileName("vidxa");
126 m_remove_file
= TRUE
;
127 wxFileOutputStream
fout(m_filename
);
134 wxVideoXANIM::wxVideoXANIM(const wxString
& filename
)
136 m_internal
= new wxXANIMinternal
;
137 m_xanim_detector
= new wxVideoXANIMProcess(this);
138 m_xanim_started
= FALSE
;
141 m_filename
= filename
;
142 m_remove_file
= FALSE
;
149 wxVideoXANIM::~wxVideoXANIM()
154 delete m_xanim_detector
;
157 wxRemoveFile(m_filename
);
160 // -------------------------------------------------------------------------
163 bool wxVideoXANIM::Play()
165 if (!m_paused
&& m_xanim_started
)
167 if (!m_video_output
) {
168 wxVideoCreateFrame(this);
172 // The movie starts with xanim
173 if (RestartXANIM()) {
180 bool wxVideoXANIM::Pause()
182 if (!m_paused
&& SendCommand(" ")) {
189 bool wxVideoXANIM::Resume()
191 if (m_paused
&& SendCommand(" ")) {
198 bool wxVideoXANIM::Stop()
200 if (!m_xanim_started
)
205 // We are waiting for the termination of the subprocess.
206 while (m_xanim_started
) {
215 // -------------------------------------------------------------------------
216 // Movie size controller
218 bool wxVideoXANIM::SetSize(wxSize size
)
223 m_video_output
->SetSize(size
.GetWidth(), size
.GetHeight());
227 bool wxVideoXANIM::GetSize(wxSize
& size
) const
231 size
.Set(m_size
[0], m_size
[1]);
235 // -------------------------------------------------------------------------
236 // Capabilities of XAnim
238 bool wxVideoXANIM::IsCapable(wxVideoType v_type
) const
240 if (v_type
== wxVIDEO_MSAVI
|| v_type
== wxVIDEO_MPEG
||
241 v_type
== wxVIDEO_QT
|| v_type
== wxVIDEO_GIF
|| v_type
== wxVIDEO_JMOV
||
242 v_type
== wxVIDEO_FLI
|| v_type
== wxVIDEO_IFF
|| v_type
== wxVIDEO_SGI
)
248 // -------------------------------------------------------------------------
251 wxString
wxVideoXANIM::GetMovieCodec() const
258 wxString
wxVideoXANIM::GetAudioCodec() const
265 wxUint32
wxVideoXANIM::GetSampleRate() const
272 wxUint8
wxVideoXANIM::GetChannels() const
279 wxUint8
wxVideoXANIM::GetBPS() const
286 double wxVideoXANIM::GetFrameRate() const
293 wxUint32
wxVideoXANIM::GetNbFrames() const
301 bool wxVideoXANIM::IsPaused() const
306 bool wxVideoXANIM::IsStopped() const
308 return !m_xanim_started
;
311 // -------------------------------------------------------------------------
314 bool wxVideoXANIM::AttachOutput(wxWindow
& out
)
316 if (!wxVideoBaseDriver::AttachOutput(out
))
322 void wxVideoXANIM::DetachOutput()
325 m_xanim_started
= FALSE
;
328 wxVideoBaseDriver::DetachOutput();
331 // -------------------------------------------------------------------------
332 // Lowlevel XAnim controller
334 bool wxVideoXANIM::SendCommand(const char *command
, char **ret
,
337 if (!m_xanim_started
)
341 // Send a command to XAnim through X11 Property
342 XChangeProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
343 m_internal
->xanim_atom
,
344 XA_STRING
, 8, PropModeReplace
, (unsigned char *)command
,
346 XFlush(m_internal
->xanim_dpy
);
352 XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
353 m_internal
->xanim_ret
, 0, 16, True
, AnyPropertyType
,
354 &prop_type
, &prop_format
, (unsigned long *)size
,
355 &extra
, (unsigned char **)ret
);
360 bool wxVideoXANIM::CollectInfo()
362 wxVideoXANIMOutput
*xanimProcess
;
363 wxString xanim_command
;
364 wxStringTokenizer tokenizer
;
366 xanimProcess
= new wxVideoXANIMOutput
;
367 xanim_command
= wxT("xanim +v +Zv -Ae ");
368 xanim_command
+= m_filename
;
369 if (!wxExecute(xanim_command
, FALSE
, xanimProcess
))
372 wxInputStream
*infoStream
= xanimProcess
->GetInputStream();
373 wxString totalOutput
;
375 while (infoStream
->GetLastError() == wxSTREAM_NO_ERROR
) {
378 infoStream
->Read(line
, sizeof(line
)-1);
379 if (infoStream
->LastRead() == 0)
382 line
[infoStream
->LastRead()] = 0;
387 // This is good for everything ... :-)
388 int position
= totalOutput
.Find(wxT("Video Codec:"));
390 totalOutput
.Remove(0, position
+13);
392 position
= totalOutput
.Find(wxT("depth="));
393 m_movieCodec
= totalOutput(0, position
);
395 totalOutput
.Remove(0, position
);
396 tokenizer
.SetString(totalOutput
, "\n\r");
398 // the rest of the line
399 wxString token
= tokenizer
.GetNextToken();
400 unsigned long my_long
;
403 totalOutput.ToULong(&my_long); \
407 totalOutput
= tokenizer
.GetString();
408 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
410 position
= totalOutput
.Find(wxT("Rate"));
411 m_audioCodec
= totalOutput(0, position
-1);
414 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
415 GETINT(m_sampleRate
);
417 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
420 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
423 tokenizer
.Reinit(totalOutput
);
424 tokenizer
.GetNextToken();
425 totalOutput
= tokenizer
.GetString();
426 totalOutput
.Remove(0, totalOutput
.Find(wxT(":"))+2);
428 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
431 totalOutput
.Remove(0,1);
434 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
437 totalOutput
.Remove(0, totalOutput
.Find(wxT("="))+1);
438 totalOutput
.ToDouble(&m_frameRate
);
440 // We wait for the conclusion
441 while (!xanimProcess
->IsTerminated())
449 bool wxVideoXANIM::RestartXANIM()
451 wxString xanim_command
;
455 unsigned long nitems
;
460 if (!m_video_output
|| m_xanim_started
)
463 // Check if we can change the size of the window dynamicly
464 xanim_chg_size
= TRUE
;
465 // Get current display
467 m_internal
->xanim_dpy
= gdk_display
;
468 GtkPizza
*pizza
= GTK_PIZZA( m_video_output
->m_wxwindow
);
469 GdkWindow
*window
= pizza
->bin_window
;
471 m_internal
->xanim_window
= GDK_WINDOW_XWINDOW(window
);
473 // Get the XANIM atom
474 m_internal
->xanim_atom
= XInternAtom(m_internal
->xanim_dpy
,
475 "XANIM_PROPERTY", False
);
478 xanim_command
.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
479 "+Av70 %s %s"), m_internal
->xanim_window
,
480 (xanim_chg_size
) ? _T("") : _T(""),
481 WXSTRINGCAST m_filename
);
484 if (!wxExecute(xanim_command
, FALSE
, m_xanim_detector
))
487 // Wait for XAnim to be ready
489 m_xanim_started
= TRUE
;
490 while (nitems
== 0 && m_xanim_started
) {
491 ret
= XGetWindowProperty(m_internal
->xanim_dpy
, m_internal
->xanim_window
,
492 m_internal
->xanim_atom
,
493 0, 4, False
, AnyPropertyType
, &prop_type
,
494 &prop_format
, &nitems
, &extra
,
495 (unsigned char **)&prop
);
501 vibrato_size
= m_video_output
->GetSize();
503 vibrato_size
.SetWidth(vibrato_size
.GetWidth()+1);
504 m_video_output
->SetSize(vibrato_size
);
505 vibrato_size
.SetWidth(vibrato_size
.GetWidth()-1);
506 m_video_output
->SetSize(vibrato_size
);
507 // Very useful ! Actually it "should" sends a SETSIZE event to XAnim
508 // FIXME: This event is not sent !!