]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/mmedia/vidxanm.cpp
wxX11:
[wxWidgets.git] / contrib / src / mmedia / vidxanm.cpp
CommitLineData
e8482f24
GL
1// -------------------------------------------------------------------------
2// Name: vidxanm.cpp
3// Purpose: wxMMedia
4// Author: Guilhem Lavaux
5// Created: 1997
6// Updated: 1998
7// Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
8// License: wxWindows license
9// -------------------------------------------------------------------------
10
11#ifdef __GNUG__
12#pragma implementation "vidxanm.h"
13#endif
14
92a19c2e 15#include "wx/wxprec.h"
e8482f24
GL
16
17#ifndef WX_PRECOMP
18#include <wx/wx.h>
19#endif
20
c9ce02ac 21#ifdef __WXGTK__
e8482f24
GL
22// Pizza !
23#include <wx/gtk/win_gtk.h>
c9ce02ac 24#endif
e8482f24
GL
25
26#include <X11/Xlib.h>
27#include <X11/Intrinsic.h>
28#ifdef __WXGTK__
29#include <gtk/gtkwidget.h>
30#include <gtk/gtkwindow.h>
31#include <gdk/gdk.h>
32#include <gdk/gdkprivate.h>
33#endif
34
35#include <wx/filefn.h>
36#include <wx/wfstream.h>
37#include <wx/datstrm.h>
38#include <wx/tokenzr.h>
39
40#define WXMMEDIA_INTERNAL
41#include "wx/mmedia/vidbase.h"
42#include "wx/mmedia/vidxanm.h"
43
44IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
45
46// -------------------------------------------------------------------------
47// End process detector
48
49class wxVideoXANIMProcess: public wxProcess {
50public:
51 wxVideoXANIMProcess(wxVideoXANIM *xanim);
52
53 void OnTerminate(int pid, int status);
54
55protected:
56 wxVideoXANIM *m_vid_xanim;
57};
58
59class wxVideoXANIMOutput: public wxProcess {
60public:
61 wxVideoXANIMOutput();
62
63 void OnTerminate(int pid, int status);
64
65 bool IsTerminated() const;
66protected:
67 bool m_terminated;
68};
69
70// -------------------------------------------------------------------------
71// XAnim video driver (process handling implementation)
72
73wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM *xanim)
74{
75 m_vid_xanim = xanim;
76}
77
78void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
79{
80 m_vid_xanim->m_xanim_started = FALSE;
81 m_vid_xanim->OnFinished();
82}
83
84wxVideoXANIMOutput::wxVideoXANIMOutput()
85 : wxProcess(NULL, -1)
86{
87 m_terminated = FALSE;
88 Redirect();
89}
90
91bool wxVideoXANIMOutput::IsTerminated() const
92{
93 return m_terminated;
94}
95
96void wxVideoXANIMOutput::OnTerminate(int pid, int status)
97{
98 m_terminated = TRUE;
99}
100
101// -------------------------------------------------------------------------
102// XAnim video driver (implementation)
103
104wxVideoXANIM::wxVideoXANIM()
105 : wxVideoBaseDriver()
106{
107 m_internal = new wxXANIMinternal;
108 m_xanim_detector = new wxVideoXANIMProcess(this);
109 m_xanim_started = FALSE;
110 m_paused = FALSE;
111 m_filename = "";
112 m_remove_file = FALSE;
113}
114
115wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
116 : wxVideoBaseDriver(str)
117{
118 m_internal = new wxXANIMinternal;
119 m_xanim_detector = new wxVideoXANIMProcess(this);
120 m_xanim_started = FALSE;
121 m_paused = FALSE;
122 m_size[0] = 0;
123 m_size[1] = 0;
124
125 m_filename = wxGetTempFileName("vidxa");
126 m_remove_file = TRUE;
127 wxFileOutputStream fout(m_filename);
128
129 fout << str;
130
131 CollectInfo();
132}
133
134wxVideoXANIM::wxVideoXANIM(const wxString& filename)
135{
136 m_internal = new wxXANIMinternal;
137 m_xanim_detector = new wxVideoXANIMProcess(this);
138 m_xanim_started = FALSE;
139 m_paused = FALSE;
140
141 m_filename = filename;
142 m_remove_file = FALSE;
143 m_size[0] = 0;
144 m_size[1] = 0;
145
146 CollectInfo();
147}
148
149wxVideoXANIM::~wxVideoXANIM()
150{
151 if (m_xanim_started)
152 Stop();
153 delete m_internal;
154 delete m_xanim_detector;
155
156 if (m_remove_file)
157 wxRemoveFile(m_filename);
158}
159
160// -------------------------------------------------------------------------
161// Movie controller
162
163bool wxVideoXANIM::Play()
164{
165 if (!m_paused && m_xanim_started)
166 return TRUE;
167 if (!m_video_output) {
168 wxVideoCreateFrame(this);
169 return TRUE;
170 }
171
172 // The movie starts with xanim
173 if (RestartXANIM()) {
174 m_paused = FALSE;
175 return TRUE;
176 }
177 return FALSE;
178}
179
180bool wxVideoXANIM::Pause()
181{
182 if (!m_paused && SendCommand(" ")) {
183 m_paused = TRUE;
184 return TRUE;
185 }
186 return FALSE;
187}
188
189bool wxVideoXANIM::Resume()
190{
191 if (m_paused && SendCommand(" ")) {
192 m_paused = FALSE;
193 return TRUE;
194 }
195 return FALSE;
196}
197
198bool wxVideoXANIM::Stop()
199{
200 if (!m_xanim_started)
201 return FALSE;
202
203 SendCommand("q");
204
205 // We are waiting for the termination of the subprocess.
206 while (m_xanim_started) {
207 wxYield();
208 }
209
210 m_paused = FALSE;
211
212 return TRUE;
213}
214
215// -------------------------------------------------------------------------
216// Movie size controller
217
218bool wxVideoXANIM::SetSize(wxSize size)
219{
220 if (!m_video_output)
221 return FALSE;
222
223 m_video_output->SetSize(size.GetWidth(), size.GetHeight());
224 return FALSE;
225}
226
227bool wxVideoXANIM::GetSize(wxSize& size) const
228{
229 if (m_size[0] == 0)
230 return FALSE;
231 size.Set(m_size[0], m_size[1]);
232 return TRUE;
233}
234
235// -------------------------------------------------------------------------
236// Capabilities of XAnim
237
238bool wxVideoXANIM::IsCapable(wxVideoType v_type) const
239{
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)
243 return TRUE;
244 else
245 return FALSE;
246}
247
248// -------------------------------------------------------------------------
249// Movie state
250
251wxString wxVideoXANIM::GetMovieCodec() const
252{
253 if (m_size[0] == 0)
254 return wxT("");
255 return m_movieCodec;
256}
257
258wxString wxVideoXANIM::GetAudioCodec() const
259{
260 if (m_size[0] == 0)
261 return wxT("");
262 return m_audioCodec;
263}
264
265wxUint32 wxVideoXANIM::GetSampleRate() const
266{
267 if (m_size[0] == 0)
268 return 0;
269 return m_sampleRate;
270}
271
272wxUint8 wxVideoXANIM::GetChannels() const
273{
274 if (m_size[0] == 0)
275 return 0;
276 return m_channels;
277}
278
279wxUint8 wxVideoXANIM::GetBPS() const
280{
281 if (m_size[0] == 0)
282 return 0;
283 return m_bps;
284}
285
286double wxVideoXANIM::GetFrameRate() const
287{
288 if (m_size[0] == 0)
289 return 0.0;
290 return m_frameRate;
291}
292
293wxUint32 wxVideoXANIM::GetNbFrames() const
294{
295 if (m_size[0] == 0)
296 return 0;
297 return m_frames;
298}
299
300
301bool wxVideoXANIM::IsPaused() const
302{
303 return m_paused;
304}
305
306bool wxVideoXANIM::IsStopped() const
307{
308 return !m_xanim_started;
309}
310
311// -------------------------------------------------------------------------
312// Output management
313
314bool wxVideoXANIM::AttachOutput(wxWindow& out)
315{
316 if (!wxVideoBaseDriver::AttachOutput(out))
317 return FALSE;
318
319 return TRUE;
320}
321
322void wxVideoXANIM::DetachOutput()
323{
324 SendCommand("q");
325 m_xanim_started = FALSE;
326 m_paused = FALSE;
327
328 wxVideoBaseDriver::DetachOutput();
329}
330
331// -------------------------------------------------------------------------
332// Lowlevel XAnim controller
333
334bool wxVideoXANIM::SendCommand(const char *command, char **ret,
335 wxUint32 *size)
336{
337 if (!m_xanim_started)
338 if (!RestartXANIM())
339 return FALSE;
340
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,
345 strlen(command));
346 XFlush(m_internal->xanim_dpy);
347 if (ret) {
348 int prop_format;
349 Atom prop_type;
350 unsigned long extra;
351
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);
356 }
357 return TRUE;
358}
359
360bool wxVideoXANIM::CollectInfo()
361{
362 wxVideoXANIMOutput *xanimProcess;
363 wxString xanim_command;
364 wxStringTokenizer tokenizer;
365
366 xanimProcess = new wxVideoXANIMOutput;
367 xanim_command = wxT("xanim +v +Zv -Ae ");
368 xanim_command += m_filename;
369 if (!wxExecute(xanim_command, FALSE, xanimProcess))
370 return FALSE;
371
372 wxInputStream *infoStream = xanimProcess->GetInputStream();
373 wxString totalOutput;
374
375 while (infoStream->LastError() == wxSTREAM_NOERROR) {
376 char line[100];
377
378 infoStream->Read(line, sizeof(line)-1);
379 if (infoStream->LastRead() == 0)
380 break;
381
382 line[infoStream->LastRead()] = 0;
383
384 totalOutput += line;
385 }
386
387 // This is good for everything ... :-)
388 int position = totalOutput.Find(wxT("Video Codec:"));
389
390 totalOutput.Remove(0, position+13);
391
392 position = totalOutput.Find(wxT("depth="));
393 m_movieCodec = totalOutput(0, position);
394
395 totalOutput.Remove(0, position);
396 tokenizer.SetString(totalOutput, "\n\r");
397
398 // the rest of the line
399 wxString token = tokenizer.GetNextToken();
400 unsigned long my_long;
401
402#define GETINT(i) \
403totalOutput.ToULong(&my_long); \
404i = my_long;
405
406 // 'Audio Codec:'
407 totalOutput = tokenizer.GetString();
408 totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
409
410 position = totalOutput.Find(wxT("Rate"));
411 m_audioCodec = totalOutput(0, position-1);
412
413 // 'Rate='
414 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
415 GETINT(m_sampleRate);
416 // 'Chans='
417 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
418 GETINT(m_channels);
419 // 'Bps='
420 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
421 GETINT(m_bps);
422 // 'Frame Stats:'
423 tokenizer.Reinit(totalOutput);
424 tokenizer.GetNextToken();
425 totalOutput = tokenizer.GetString();
426 totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
427 // 'Size='
428 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
429 GETINT(m_size[0]);
430 // 'x'
431 totalOutput.Remove(0,1);
432 GETINT(m_size[1]);
433 // 'Frames='
434 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
435 GETINT(m_frames);
436 // 'avfps='
437 totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
438 totalOutput.ToDouble(&m_frameRate);
439
440 // We wait for the conclusion
441 while (!xanimProcess->IsTerminated())
442 wxYield();
443
444 delete xanimProcess;
445
446 return TRUE;
447}
448
449bool wxVideoXANIM::RestartXANIM()
450{
451 wxString xanim_command;
452 int ret;
453 Atom prop_type;
454 int prop_format;
455 unsigned long nitems;
456 unsigned long extra;
457 char prop[4];
458 bool xanim_chg_size;
459
460 if (!m_video_output || m_xanim_started)
461 return FALSE;
462
463 // Check if we can change the size of the window dynamicly
464 xanim_chg_size = TRUE;
465 // Get current display
466#ifdef __WXGTK__
467 m_internal->xanim_dpy = gdk_display;
468 GtkPizza *pizza = GTK_PIZZA( m_video_output->m_wxwindow );
469 GdkWindow *window = pizza->bin_window;
470
471 m_internal->xanim_window =
472 ((GdkWindowPrivate *)window)->xwindow;
473#endif
474 // Get the XANIM atom
475 m_internal->xanim_atom = XInternAtom(m_internal->xanim_dpy,
476 "XANIM_PROPERTY", False);
477
478 // Build the command
479 xanim_command.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
480 "+Av70 %s %s"), m_internal->xanim_window,
481 (xanim_chg_size) ? _T("") : _T(""),
482 WXSTRINGCAST m_filename);
483
484 // Execute it
485 if (!wxExecute(xanim_command, FALSE, m_xanim_detector))
486 return FALSE;
487
488 // Wait for XAnim to be ready
489 nitems = 0;
490 m_xanim_started = TRUE;
491 while (nitems == 0 && m_xanim_started) {
492 ret = XGetWindowProperty(m_internal->xanim_dpy, m_internal->xanim_window,
493 m_internal->xanim_atom,
494 0, 4, False, AnyPropertyType, &prop_type,
495 &prop_format, &nitems, &extra,
496 (unsigned char **)&prop);
497 wxYield();
498 }
499
500 wxSize vibrato_size;
501
502 vibrato_size = m_video_output->GetSize();
503
504 vibrato_size.SetWidth(vibrato_size.GetWidth()+1);
505 m_video_output->SetSize(vibrato_size);
506 vibrato_size.SetWidth(vibrato_size.GetWidth()-1);
507 m_video_output->SetSize(vibrato_size);
c42b1de6
GL
508 // Very useful ! Actually it "should" sends a SETSIZE event to XAnim
509 // FIXME: This event is not sent !!
e8482f24
GL
510
511 m_paused = FALSE;
512
513 return TRUE;
514}