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