From 2018e574e7dfa7bf508a703add4f6d4fa6fb8758 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Fri, 25 Feb 2000 09:08:52 +0000 Subject: [PATCH] Major changes in wxVidXANIM (support for output filtering) Several API addings Added process.cpp, process.h and utilsunx.cpp in wxMMedia directory They should be moved to src/unix, src/common and include/wx to use them git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6280 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- utils/wxMMedia2/README | 10 +- utils/wxMMedia2/board/Makefile.in | 8 +- utils/wxMMedia2/board/mmbman.cpp | 28 +- utils/wxMMedia2/board/mmboard.cpp | 2 + utils/wxMMedia2/lib/Makefile.in | 2 +- utils/wxMMedia2/lib/sndaiff.cpp | 5 + utils/wxMMedia2/lib/sndaiff.h | 25 +- utils/wxMMedia2/lib/sndfile.cpp | 5 + utils/wxMMedia2/lib/sndfile.h | 4 + utils/wxMMedia2/lib/sndwav.cpp | 5 + utils/wxMMedia2/lib/sndwav.h | 43 +- utils/wxMMedia2/lib/vidbase.h | 21 +- utils/wxMMedia2/lib/vidxanm.cpp | 229 ++++++++- utils/wxMMedia2/lib/vidxanm.h | 36 +- utils/wxMMedia2/process.cpp | 85 ++++ utils/wxMMedia2/process.h | 86 ++++ utils/wxMMedia2/utilsunx.cpp | 798 ++++++++++++++++++++++++++++++ 17 files changed, 1326 insertions(+), 66 deletions(-) create mode 100644 utils/wxMMedia2/process.cpp create mode 100644 utils/wxMMedia2/process.h create mode 100644 utils/wxMMedia2/utilsunx.cpp diff --git a/utils/wxMMedia2/README b/utils/wxMMedia2/README index c77db4f392..bf90fb56cd 100644 --- a/utils/wxMMedia2/README +++ b/utils/wxMMedia2/README @@ -30,10 +30,18 @@ Video features: time Video bugs: - * Recode windows port + * AVI file works on Windows CD features: * standard access to the CDAUDIO interface CD bugs: +---------------- +| INSTALLATION | +---------------- + +You need to move the three files included in this directory: + - utilsunx.cpp => src/unix + - process.cpp => src/common + - process.h => include/wx diff --git a/utils/wxMMedia2/board/Makefile.in b/utils/wxMMedia2/board/Makefile.in index c2d3ac1c61..5a78dfddeb 100644 --- a/utils/wxMMedia2/board/Makefile.in +++ b/utils/wxMMedia2/board/Makefile.in @@ -15,22 +15,22 @@ program_dir = utils/wxMMedia2/board PROGRAM=mmboard -OBJECTS=$(PROGRAM).o +OBJECTS=mmboard.o mmbman.o EXTRA_CPPFLAGS= -I$(top_srcdir)/utils/wxMMedia2/lib -EXTRA_LIBS= ../lib/libwxmmedia2.a +EXTRA_LIBS= ../lib/libwxmmedia2.a -lesd # the comment at the end of the next line is needed because otherwise autoconf # would remove this line completely - it contains a built-in hack to remove # any VPATH assignment not containing ':' -VPATH = @PATH_IFS@$(top_srcdir)/utils/wxMMedia2/sample # ':' for autoconf +VPATH = @PATH_IFS@$(top_srcdir)/utils/wxMMedia2/board # ':' for autoconf include ../../../src/make.env .SUFFIXES: .o .cpp .c .cpp.o: - $(CC) $(CPPFLAGS) $(EXTRA_CPPFLAGS) -o $@ $< + $(CC) -c $(CPPFLAGS) $(EXTRA_CPPFLAGS) -o $@ $< all: $(PROGRAM) diff --git a/utils/wxMMedia2/board/mmbman.cpp b/utils/wxMMedia2/board/mmbman.cpp index 1c813e1624..61f5f29b85 100644 --- a/utils/wxMMedia2/board/mmbman.cpp +++ b/utils/wxMMedia2/board/mmbman.cpp @@ -126,7 +126,6 @@ public: protected: wxWindow *m_output_window; - wxInputStream *m_input_stream; wxVideoBaseDriver *m_video_driver; }; @@ -333,8 +332,6 @@ MMBoardVideoFile::~MMBoardVideoFile() { if (m_video_driver) delete m_video_driver; - - delete m_input_stream; } bool MMBoardVideoFile::NeedWindow() @@ -346,6 +343,12 @@ void MMBoardVideoFile::SetWindow(wxWindow *window) { m_output_window = window; m_video_driver->AttachOutput(*window); + + wxSize size; + m_video_driver->GetSize(size); + window->SetSize(size); + // BAD BAD + window->GetParent()->GetSizer()->Fit(window->GetParent()); } void MMBoardVideoFile::Play() @@ -379,9 +382,13 @@ MMBoardTime MMBoardVideoFile::GetPosition() MMBoardTime MMBoardVideoFile::GetLength() { MMBoardTime btime; + int frameTime; - btime.seconds = 1; - btime.minutes = btime.hours = 0; + frameTime = (int)( m_video_driver->GetNbFrames() / m_video_driver->GetFrameRate()); + + btime.seconds = frameTime % 60; + btime.minutes = (frameTime / 60) % 60; + btime.hours = frameTime / 3600; return btime; } @@ -402,7 +409,16 @@ wxString MMBoardVideoFile::GetStringType() wxString MMBoardVideoFile::GetStringInformation() { - return wxString(wxT("No info")); + wxString info; + + info = wxT("Video codec: "); + info += m_video_driver->GetMovieCodec() + "\n"; + info += wxT("Audio codec: "); + info += m_video_driver->GetAudioCodec(); + info += wxString::Format(" Sample rate: %d Channels: %d\n", m_video_driver->GetSampleRate(), + m_video_driver->GetBPS()); + info += wxString::Format(" Frame rate: %.01f", m_video_driver->GetFrameRate()); + return info; } // ---------------------------------------------------------------------------- diff --git a/utils/wxMMedia2/board/mmboard.cpp b/utils/wxMMedia2/board/mmboard.cpp index 4291ca950a..15e70bc960 100644 --- a/utils/wxMMedia2/board/mmboard.cpp +++ b/utils/wxMMedia2/board/mmboard.cpp @@ -205,11 +205,13 @@ wxUint8 MMBoardApp::TestMultimediaCaps() // We test the OSS (Open Sound System) support. +#if 0 dev = new wxSoundStreamOSS(); if (dev->GetError() == wxSOUND_NOERR) caps |= MM_SOUND_OSS; delete dev; #endif +#endif #ifdef __WIN32__ // We test the Windows sound support. diff --git a/utils/wxMMedia2/lib/Makefile.in b/utils/wxMMedia2/lib/Makefile.in index 9b11ab675d..511e832f46 100644 --- a/utils/wxMMedia2/lib/Makefile.in +++ b/utils/wxMMedia2/lib/Makefile.in @@ -17,7 +17,7 @@ VPATH= $(top_srcdir)/utils/wxMMedia2/lib LIBTARGET=libwxmmedia2 OBJECTS=sndbase.o sndcodec.o sndpcm.o sndcpcm.o sndulaw.o sndfile.o sndoss.o\ - sndaiff.o sndwav.o sndg72x.o \ + sndesd.o sndaiff.o sndwav.o sndg72x.o \ g711.o g721.o g723_24.o g723_40.o g72x.o \ cdbase.o cdunix.o \ vidbase.o vidxanm.o diff --git a/utils/wxMMedia2/lib/sndaiff.cpp b/utils/wxMMedia2/lib/sndaiff.cpp index 1d450edfa4..2242cc263d 100644 --- a/utils/wxMMedia2/lib/sndaiff.cpp +++ b/utils/wxMMedia2/lib/sndaiff.cpp @@ -42,6 +42,11 @@ wxSoundAiff::~wxSoundAiff() { } +wxString wxSoundAiff::GetCodecName() const +{ + return "wxSoundAiff codec"; +} + bool wxSoundAiff::CanRead() { wxUint32 signature1, signature2, len; diff --git a/utils/wxMMedia2/lib/sndaiff.h b/utils/wxMMedia2/lib/sndaiff.h index bd9750380b..20539e6fb0 100644 --- a/utils/wxMMedia2/lib/sndaiff.h +++ b/utils/wxMMedia2/lib/sndaiff.h @@ -23,19 +23,20 @@ class wxSoundAiff: public wxSoundFileStream { public: - wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound); - wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound); - ~wxSoundAiff(); - - bool CanRead(); - + wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound); + wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound); + ~wxSoundAiff(); + + bool CanRead(); + wxString GetCodecName() const; + protected: - bool PrepareToPlay(); - bool PrepareToRecord(unsigned long time); - bool FinishRecording(); - - wxUint32 GetData(void *buffer, wxUint32 len); - wxUint32 PutData(const void *buffer, wxUint32 len); + bool PrepareToPlay(); + bool PrepareToRecord(unsigned long time); + bool FinishRecording(); + + wxUint32 GetData(void *buffer, wxUint32 len); + wxUint32 PutData(const void *buffer, wxUint32 len); }; #endif diff --git a/utils/wxMMedia2/lib/sndfile.cpp b/utils/wxMMedia2/lib/sndfile.cpp index d5cec0e66f..eea2ec9043 100644 --- a/utils/wxMMedia2/lib/sndfile.cpp +++ b/utils/wxMMedia2/lib/sndfile.cpp @@ -317,6 +317,11 @@ void wxSoundFileStream::FinishPreparation(wxUint32 len) m_prepared = TRUE; } +wxString wxSoundFileStream::GetCodecName() const +{ + return wxString(wxT("wxSoundFileStream base codec")); +} + wxUint32 wxSoundFileStream::GetLength() { if (m_input && !m_prepared && GetError() == wxSOUND_NOERR) diff --git a/utils/wxMMedia2/lib/sndfile.h b/utils/wxMMedia2/lib/sndfile.h index e6efd74780..c6fc91ad2c 100644 --- a/utils/wxMMedia2/lib/sndfile.h +++ b/utils/wxMMedia2/lib/sndfile.h @@ -90,6 +90,10 @@ class wxSoundFileStream: public wxSoundStream { // For this action, you must use wxSoundRouterStream applied to wxSoundFileStream. bool SetSoundFormat(const wxSoundFormatBase& format); + // This function returns the Codec name. This is useful for those who want to build + // a player (But also in some other case). + virtual wxString GetCodecName() const; + // You should use this function to test whether this file codec can read the stream you passed // to it. virtual bool CanRead() { return FALSE; } diff --git a/utils/wxMMedia2/lib/sndwav.cpp b/utils/wxMMedia2/lib/sndwav.cpp index 509a004009..f1dbc0eca8 100644 --- a/utils/wxMMedia2/lib/sndwav.cpp +++ b/utils/wxMMedia2/lib/sndwav.cpp @@ -48,6 +48,11 @@ wxSoundWave::~wxSoundWave() { } +wxString wxSoundWave::GetCodecName() const +{ + return wxString(wxT("wxSoundWave codec")); +} + #define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; } bool wxSoundWave::CanRead() diff --git a/utils/wxMMedia2/lib/sndwav.h b/utils/wxMMedia2/lib/sndwav.h index 7d4e380fe2..f9930c192d 100644 --- a/utils/wxMMedia2/lib/sndwav.h +++ b/utils/wxMMedia2/lib/sndwav.h @@ -25,28 +25,29 @@ class wxSoundWave: public wxSoundFileStream { public: - wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound); - wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound); - ~wxSoundWave(); - - bool CanRead(); - + wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound); + wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound); + ~wxSoundWave(); + + bool CanRead(); + wxString GetCodecName() const; + protected: - bool PrepareToPlay(); - bool PrepareToRecord(unsigned long time); - bool FinishRecording(); - - wxUint32 GetData(void *buffer, wxUint32 len); - wxUint32 PutData(const void *buffer, wxUint32 len); - - bool HandleOutputPCM(wxDataInputStream& data, wxUint16 channels, - wxUint32 sample_fq, wxUint32 byte_p_sec, - wxUint16 byte_p_spl, wxUint16 bits_p_spl); - bool HandleOutputG721(wxDataInputStream& data, wxUint16 channels, - wxUint32 sample_fq, wxUint32 byte_p_sec, - wxUint16 byte_p_spl, wxUint16 bits_p_spl); - wxSoundFormatBase *HandleInputPCM(wxDataOutputStream& data); - wxSoundFormatBase *HandleInputG72X(wxDataOutputStream& data); + bool PrepareToPlay(); + bool PrepareToRecord(unsigned long time); + bool FinishRecording(); + + wxUint32 GetData(void *buffer, wxUint32 len); + wxUint32 PutData(const void *buffer, wxUint32 len); + + bool HandleOutputPCM(wxDataInputStream& data, wxUint16 channels, + wxUint32 sample_fq, wxUint32 byte_p_sec, + wxUint16 byte_p_spl, wxUint16 bits_p_spl); + bool HandleOutputG721(wxDataInputStream& data, wxUint16 channels, + wxUint32 sample_fq, wxUint32 byte_p_sec, + wxUint16 byte_p_spl, wxUint16 bits_p_spl); + wxSoundFormatBase *HandleInputPCM(wxDataOutputStream& data); + wxSoundFormatBase *HandleInputG72X(wxDataOutputStream& data); }; #endif diff --git a/utils/wxMMedia2/lib/vidbase.h b/utils/wxMMedia2/lib/vidbase.h index 7dd24aa09d..8d5d1d55ed 100644 --- a/utils/wxMMedia2/lib/vidbase.h +++ b/utils/wxMMedia2/lib/vidbase.h @@ -73,11 +73,24 @@ public: virtual bool Resume() = 0; // Size management - virtual bool Resize(wxUint16 w, wxUint16 h) = 0; + virtual bool SetSize(wxSize size) = 0; virtual bool GetSize(wxSize& size) const = 0; // Test the capability of the driver to handle the specified type - virtual bool IsCapable(wxVideoType WXUNUSED(v_type)) { return FALSE; } + virtual bool IsCapable(wxVideoType WXUNUSED(v_type)) const { return FALSE; } + + // Return the video codec name + virtual wxString GetMovieCodec() const = 0; + // Return the audio codec name + virtual wxString GetAudioCodec() const = 0; + // Return misc info about audio + virtual wxUint32 GetSampleRate() const = 0; + virtual wxUint8 GetChannels() const = 0; + virtual wxUint8 GetBPS() const = 0; + // Return frame rate + virtual double GetFrameRate() const = 0; + // Return number of frames + virtual wxUint32 GetNbFrames() const = 0; // Called when the movie finished virtual void OnFinished() {} @@ -87,8 +100,8 @@ public: virtual void DetachOutput(); // They return the state of the movie. - virtual bool IsPaused() = 0; - virtual bool IsStopped() = 0; + virtual bool IsPaused() const = 0; + virtual bool IsStopped() const = 0; }; WXDLLEXPORT wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv); diff --git a/utils/wxMMedia2/lib/vidxanm.cpp b/utils/wxMMedia2/lib/vidxanm.cpp index a4ca4ef074..413f0c2e8b 100644 --- a/utils/wxMMedia2/lib/vidxanm.cpp +++ b/utils/wxMMedia2/lib/vidxanm.cpp @@ -32,6 +32,8 @@ #include #include +#include +#include #define WXMMEDIA_INTERNAL #include "vidbase.h" @@ -52,8 +54,19 @@ protected: wxVideoXANIM *m_vid_xanim; }; +class wxVideoXANIMOutput: public wxProcess { +public: + wxVideoXANIMOutput(); + + void OnTerminate(int pid, int status); + + bool IsTerminated() const; +protected: + bool m_terminated; +}; + // ------------------------------------------------------------------------- -// XAnim video driver (implementation) +// XAnim video driver (process handling implementation) wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM *xanim) { @@ -66,6 +79,25 @@ void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status)) m_vid_xanim->OnFinished(); } +wxVideoXANIMOutput::wxVideoXANIMOutput() + : wxProcess(NULL, TRUE, -1) +{ + m_terminated = FALSE; +} + +bool wxVideoXANIMOutput::IsTerminated() const +{ + return m_terminated; +} + +void wxVideoXANIMOutput::OnTerminate(int pid, int status) +{ + m_terminated = TRUE; +} + +// ------------------------------------------------------------------------- +// XAnim video driver (implementation) + wxVideoXANIM::wxVideoXANIM() : wxVideoBaseDriver() { @@ -84,12 +116,16 @@ wxVideoXANIM::wxVideoXANIM(wxInputStream& str) m_xanim_detector = new wxVideoXANIMProcess(this); m_xanim_started = FALSE; m_paused = FALSE; + m_size[0] = 0; + m_size[1] = 0; m_filename = wxGetTempFileName("vidxa"); m_remove_file = TRUE; wxFileOutputStream fout(m_filename); fout << str; + + CollectInfo(); } wxVideoXANIM::wxVideoXANIM(const wxString& filename) @@ -101,6 +137,10 @@ wxVideoXANIM::wxVideoXANIM(const wxString& filename) m_filename = filename; m_remove_file = FALSE; + m_size[0] = 0; + m_size[1] = 0; + + CollectInfo(); } wxVideoXANIM::~wxVideoXANIM() @@ -114,6 +154,9 @@ wxVideoXANIM::~wxVideoXANIM() wxRemoveFile(m_filename); } +// ------------------------------------------------------------------------- +// Movie controller + bool wxVideoXANIM::Play() { if (!m_paused && m_xanim_started) @@ -166,21 +209,30 @@ bool wxVideoXANIM::Stop() return TRUE; } -bool wxVideoXANIM::Resize(wxUint16 w, wxUint16 h) +// ------------------------------------------------------------------------- +// Movie size controller + +bool wxVideoXANIM::SetSize(wxSize size) { if (!m_video_output) return FALSE; - m_video_output->SetSize(w, h); + m_video_output->SetSize(size.GetWidth(), size.GetHeight()); return FALSE; } bool wxVideoXANIM::GetSize(wxSize& size) const { - return FALSE; + if (m_size[0] == 0) + return FALSE; + size.Set(m_size[0], m_size[1]); + return TRUE; } -bool wxVideoXANIM::IsCapable(wxVideoType v_type) +// ------------------------------------------------------------------------- +// Capabilities of XAnim + +bool wxVideoXANIM::IsCapable(wxVideoType v_type) const { if (v_type == wxVIDEO_MSAVI || v_type == wxVIDEO_MPEG || v_type == wxVIDEO_QT || v_type == wxVIDEO_GIF || v_type == wxVIDEO_JMOV || @@ -190,21 +242,77 @@ bool wxVideoXANIM::IsCapable(wxVideoType v_type) return FALSE; } -bool wxVideoXANIM::IsPaused() +// ------------------------------------------------------------------------- +// Movie state + +wxString wxVideoXANIM::GetMovieCodec() const +{ + if (m_size[0] == 0) + return wxT(""); + return m_movieCodec; +} + +wxString wxVideoXANIM::GetAudioCodec() const +{ + if (m_size[0] == 0) + return wxT(""); + return m_audioCodec; +} + +wxUint32 wxVideoXANIM::GetSampleRate() const +{ + if (m_size[0] == 0) + return 0; + return m_sampleRate; +} + +wxUint8 wxVideoXANIM::GetChannels() const +{ + if (m_size[0] == 0) + return 0; + return m_channels; +} + +wxUint8 wxVideoXANIM::GetBPS() const +{ + if (m_size[0] == 0) + return 0; + return m_bps; +} + +double wxVideoXANIM::GetFrameRate() const +{ + if (m_size[0] == 0) + return 0.0; + return m_frameRate; +} + +wxUint32 wxVideoXANIM::GetNbFrames() const +{ + if (m_size[0] == 0) + return 0; + return m_frames; +} + + +bool wxVideoXANIM::IsPaused() const { return m_paused; } -bool wxVideoXANIM::IsStopped() +bool wxVideoXANIM::IsStopped() const { return !m_xanim_started; } +// ------------------------------------------------------------------------- +// Output management + bool wxVideoXANIM::AttachOutput(wxWindow& out) { if (!wxVideoBaseDriver::AttachOutput(out)) return FALSE; - + return TRUE; } @@ -217,6 +325,9 @@ void wxVideoXANIM::DetachOutput() wxVideoBaseDriver::DetachOutput(); } +// ------------------------------------------------------------------------- +// Lowlevel XAnim controller + bool wxVideoXANIM::SendCommand(const char *command, char **ret, wxUint32 *size) { @@ -243,6 +354,95 @@ bool wxVideoXANIM::SendCommand(const char *command, char **ret, return TRUE; } +bool wxVideoXANIM::CollectInfo() +{ + wxVideoXANIMOutput *xanimProcess; + wxString xanim_command; + wxStringTokenizer tokenizer; + + xanimProcess = new wxVideoXANIMOutput; + xanim_command = wxT("xanim +v +Zv -Ae "); + xanim_command += m_filename; + if (!wxExecute(xanim_command, FALSE, xanimProcess)) + return FALSE; + + wxInputStream *infoStream = xanimProcess->GetInputStream(); + wxString totalOutput; + + while (infoStream->LastError() == wxSTREAM_NOERROR) { + char line[100]; + + infoStream->Read(line, sizeof(line)-1); + if (infoStream->LastRead() == 0) + break; + + line[infoStream->LastRead()] = 0; + + totalOutput += line; + } + + // This is good for everything ... :-) + int position = totalOutput.Find(wxT("Video Codec:")); + + totalOutput.Remove(0, position+13); + + position = totalOutput.Find(wxT("depth=")); + m_movieCodec = totalOutput(0, position); + + totalOutput.Remove(0, position); + tokenizer.SetString(totalOutput, "\n\r"); + + // the rest of the line + wxString token = tokenizer.GetNextToken(); + unsigned long my_long; + +#define GETINT(i) \ +totalOutput.ToULong(&my_long); \ +i = my_long; + + // 'Audio Codec:' + totalOutput = tokenizer.GetString(); + totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2); + + position = totalOutput.Find(wxT("Rate")); + m_audioCodec = totalOutput(0, position-1); + + // 'Rate=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + GETINT(m_sampleRate); + // 'Chans=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + GETINT(m_channels); + // 'Bps=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + GETINT(m_bps); + // 'Frame Stats:' + tokenizer.Reinit(totalOutput); + tokenizer.GetNextToken(); + totalOutput = tokenizer.GetString(); + totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2); + // 'Size=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + GETINT(m_size[0]); + // 'x' + totalOutput.Remove(0,1); + GETINT(m_size[1]); + // 'Frames=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + GETINT(m_frames); + // 'avfps=' + totalOutput.Remove(0, totalOutput.Find(wxT("="))+1); + totalOutput.ToDouble(&m_frameRate); + + // We wait for the conclusion + while (!xanimProcess->IsTerminated()) + wxYield(); + + delete xanimProcess; + + return TRUE; +} + bool wxVideoXANIM::RestartXANIM() { wxString xanim_command; @@ -278,7 +478,7 @@ bool wxVideoXANIM::RestartXANIM() (xanim_chg_size) ? _T("") : _T(""), WXSTRINGCAST m_filename); - // Execute it + // Execute it if (!wxExecute(xanim_command, FALSE, m_xanim_detector)) return FALSE; @@ -294,8 +494,15 @@ bool wxVideoXANIM::RestartXANIM() wxYield(); } - m_video_output->SetSize(m_video_output->GetSize()); - // Very useful ! Actually it sends a SETSIZE event to XAnim + wxSize vibrato_size; + + vibrato_size = m_video_output->GetSize(); + + vibrato_size.SetWidth(vibrato_size.GetWidth()+1); + m_video_output->SetSize(vibrato_size); + vibrato_size.SetWidth(vibrato_size.GetWidth()-1); + m_video_output->SetSize(vibrato_size); + // Very useful ! Actually it sends a SETSIZE event to XAnim m_paused = FALSE; diff --git a/utils/wxMMedia2/lib/vidxanm.h b/utils/wxMMedia2/lib/vidxanm.h index 648e8816db..6c82f2e089 100644 --- a/utils/wxMMedia2/lib/vidxanm.h +++ b/utils/wxMMedia2/lib/vidxanm.h @@ -67,7 +67,7 @@ typedef struct wxXANIMinternal { class WXDLLEXPORT wxVideoXANIM : public wxVideoBaseDriver { DECLARE_DYNAMIC_CLASS(wxVideoXANIM) -protected: + protected: // Remember the state of the subprocess bool m_xanim_started, m_paused; // Pure X11 variables @@ -76,7 +76,15 @@ protected: wxProcess *m_xanim_detector; // Remember to delete the temporary file when necessary bool m_remove_file; -public: + wxUint32 m_size[2]; + wxUint32 m_sampleRate; + wxUint8 m_channels; + wxUint8 m_bps; + wxUint32 m_frames; + double m_frameRate; + wxString m_movieCodec, m_audioCodec; + + public: wxVideoXANIM(); wxVideoXANIM(wxInputStream& str); wxVideoXANIM(const wxString& filename); @@ -88,16 +96,29 @@ public: bool Stop(); bool SetVolume(wxUint8 vol); - bool Resize(wxUint16 w, wxUint16 h); + bool SetSize(wxSize size); bool GetSize(wxSize& size) const; - bool IsCapable(wxVideoType v_type); + // Return the video codec name + wxString GetMovieCodec() const; + // Return the audio codec name + wxString GetAudioCodec() const; + // Return misc info about audio + wxUint32 GetSampleRate() const; + wxUint8 GetChannels() const; + wxUint8 GetBPS() const; + // Return frame rate + double GetFrameRate() const; + // Return number of frames in the movie + wxUint32 GetNbFrames() const; + + bool IsCapable(wxVideoType v_type) const; bool AttachOutput(wxWindow& output); void DetachOutput(); - bool IsPaused(); - bool IsStopped(); + bool IsPaused() const; + bool IsStopped() const; friend class wxVideoXANIMProcess; @@ -107,6 +128,9 @@ protected: // Send a command to the subprocess bool SendCommand(const char *command,char **ret = NULL, wxUint32 *size = NULL); + + // Collect informations from XAnim + bool CollectInfo(); }; #endif diff --git a/utils/wxMMedia2/process.cpp b/utils/wxMMedia2/process.cpp new file mode 100644 index 0000000000..e573fe8e0d --- /dev/null +++ b/utils/wxMMedia2/process.cpp @@ -0,0 +1,85 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: process.cpp +// Purpose: Process termination classes +// Author: Guilhem Lavaux +// Modified by: Vadim Zeitlin to check error codes, added Detach() method +// Created: 24/06/98 +// RCS-ID: $Id$ +// Copyright: (c) Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifdef __GNUG__ + #pragma implementation "process.h" +#endif + +// For compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" + +#ifdef __BORLANDC__ + #pragma hdrstop +#endif + +#ifndef WX_PRECOMP + #include "wx/defs.h" +#endif + +#include "wx/process.h" + +IMPLEMENT_DYNAMIC_CLASS(wxProcess, wxEvtHandler) +IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent) + +wxProcess::wxProcess(wxEvtHandler *parent, bool needPipe, int id) +{ + if (parent) + SetNextHandler(parent); + + m_id = id; + m_needPipe = needPipe; + m_in_stream = NULL; + m_out_stream = NULL; +} + +wxProcess::~wxProcess() +{ + if (m_in_stream) + delete m_in_stream; + if (m_out_stream) + delete m_out_stream; +} + +void wxProcess::OnTerminate(int pid, int status) +{ + wxProcessEvent event(m_id, pid, status); + + if ( !ProcessEvent(event) ) + delete this; + //else: the object which processed the event is responsible for deleting + // us! +} + +void wxProcess::Detach() +{ + SetNextHandler(NULL); +} + +void wxProcess::SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream) +{ + m_in_stream = in_stream; + m_out_stream = out_stream; +} + +wxInputStream *wxProcess::GetInputStream() const +{ + return m_in_stream; +} + +wxOutputStream *wxProcess::GetOutputStream() const +{ + return m_out_stream; +} + +bool wxProcess::NeedPipe() const +{ + return m_needPipe; +} diff --git a/utils/wxMMedia2/process.h b/utils/wxMMedia2/process.h new file mode 100644 index 0000000000..19ae35c1f6 --- /dev/null +++ b/utils/wxMMedia2/process.h @@ -0,0 +1,86 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: process.h +// Purpose: wxProcess class +// Author: Guilhem Lavaux +// Modified by: Vadim Zeitlin to check error codes, added Detach() method +// Created: 24/06/98 +// RCS-ID: $Id$ +// Copyright: (c) 1998 Guilhem Lavaux +// Licence: wxWindows license +///////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PROCESSH__ +#define _WX_PROCESSH__ + +#ifdef __GNUG__ + #pragma interface "process.h" +#endif + +#include "wx/defs.h" +#include "wx/object.h" +#include "wx/event.h" +#include "wx/stream.h" + +// Process Event handling +class WXDLLEXPORT wxProcessEvent : public wxEvent +{ +DECLARE_DYNAMIC_CLASS(wxProcessEvent) + +public: + wxProcessEvent(int id = 0, int pid = 0, int exitcode = 0) : wxEvent(id) + { + m_eventType = wxEVT_END_PROCESS; + m_pid = pid; + m_exitcode = exitcode; + } + + // accessors + // PID of process which terminated + int GetPid() { return m_pid; } + + // the exit code + int GetExitCode() { return m_exitcode; } + +public: + int m_pid, m_exitcode; +}; + +// A wxProcess object should be passed to wxExecute - than its OnTerminate() +// function will be called when the process terminates. +class WXDLLEXPORT wxProcess : public wxEvtHandler +{ +DECLARE_DYNAMIC_CLASS(wxProcess) + +public: + wxProcess(wxEvtHandler *parent = (wxEvtHandler *) NULL, bool needPipe = FALSE, int id = -1); + ~wxProcess(); + + virtual void OnTerminate(int pid, int status); + + // detach from the parent - should be called by the parent if it's deleted + // before the process it started terminates + void Detach(); + + // Pipe handling + wxInputStream *GetInputStream() const; + wxOutputStream *GetOutputStream() const; + + // These functions should not be called by the usual user. They are only + // intended to be used by wxExecute. + // Install pipes + void SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream); + bool NeedPipe() const; + +protected: + int m_id; + bool m_needPipe; + wxInputStream *m_in_stream; + wxOutputStream *m_out_stream; +}; + +typedef void (wxObject::*wxProcessEventFunction)(wxProcessEvent&); + +#define EVT_END_PROCESS(id, func) { wxEVT_END_PROCESS, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxProcessEventFunction) & func, NULL}, + +#endif + // _WX_PROCESSH__ diff --git a/utils/wxMMedia2/utilsunx.cpp b/utils/wxMMedia2/utilsunx.cpp new file mode 100644 index 0000000000..8e68bef6bc --- /dev/null +++ b/utils/wxMMedia2/utilsunx.cpp @@ -0,0 +1,798 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: utilsunx.cpp +// Purpose: generic Unix implementation of many wx functions +// Author: Vadim Zeitlin +// Id: $Id$ +// Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin +// Licence: wxWindows licence +///////////////////////////////////////////////////////////////////////////// + +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + +#include "wx/defs.h" +#include "wx/string.h" + +#include "wx/intl.h" +#include "wx/log.h" + +#include "wx/utils.h" +#include "wx/process.h" +#include "wx/thread.h" + +#include "wx/stream.h" + +#if wxUSE_GUI + #include "wx/unix/execute.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for O_WRONLY and friends +#include // nanosleep() and/or usleep() +#include // isspace() +#include // needed for FD_SETSIZE + +#ifdef HAVE_UNAME + #include // for uname() +#endif // HAVE_UNAME + +// ---------------------------------------------------------------------------- +// conditional compilation +// ---------------------------------------------------------------------------- + +// many versions of Unices have this function, but it is not defined in system +// headers - please add your system here if it is the case for your OS. +// SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this. +#if !defined(HAVE_USLEEP) && \ + (defined(__SUN__) && !defined(__SunOs_5_6) && \ + !defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \ + defined(__osf__) || defined(__EMX__) + extern "C" + { + #ifdef __SUN__ + int usleep(unsigned int usec); + #else // !Sun + #ifdef __EMX__ + /* I copied this from the XFree86 diffs. AV. */ + #define INCL_DOSPROCESS + #include + inline void usleep(unsigned long delay) + { + DosSleep(delay ? (delay/1000l) : 1l); + } + #else // !Sun && !EMX + void usleep(unsigned long usec); + #endif + #endif // Sun/EMX/Something else + }; + + #define HAVE_USLEEP 1 +#endif // Unices without usleep() + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// sleeping +// ---------------------------------------------------------------------------- + +void wxSleep(int nSecs) +{ + sleep(nSecs); +} + +void wxUsleep(unsigned long milliseconds) +{ +#if defined(HAVE_NANOSLEEP) + timespec tmReq; + tmReq.tv_sec = (time_t)(milliseconds / 1000); + tmReq.tv_nsec = (milliseconds % 1000) * 1000 * 1000; + + // we're not interested in remaining time nor in return value + (void)nanosleep(&tmReq, (timespec *)NULL); +#elif defined(HAVE_USLEEP) + // uncomment this if you feel brave or if you are sure that your version + // of Solaris has a safe usleep() function but please notice that usleep() + // is known to lead to crashes in MT programs in Solaris 2.[67] and is not + // documented as MT-Safe + #if defined(__SUN__) && wxUSE_THREADS + #error "usleep() cannot be used in MT programs under Solaris." + #endif // Sun + + usleep(milliseconds * 1000); // usleep(3) wants microseconds +#elif defined(HAVE_SLEEP) + // under BeOS sleep() takes seconds (what about other platforms, if any?) + sleep(milliseconds * 1000); +#else // !sleep function + #error "usleep() or nanosleep() function required for wxUsleep" +#endif // sleep function +} + +// ---------------------------------------------------------------------------- +// process management +// ---------------------------------------------------------------------------- + +int wxKill(long pid, wxSignal sig) +{ + return kill((pid_t)pid, (int)sig); +} + +#define WXEXECUTE_NARGS 127 + +long wxExecute( const wxString& command, bool sync, wxProcess *process ) +{ + wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") ); + + int argc = 0; + wxChar *argv[WXEXECUTE_NARGS]; + wxString argument; + const wxChar *cptr = command.c_str(); + wxChar quotechar = wxT('\0'); // is arg quoted? + bool escaped = FALSE; + + // split the command line in arguments + do + { + argument=wxT(""); + quotechar = wxT('\0'); + + // eat leading whitespace: + while ( wxIsspace(*cptr) ) + cptr++; + + if ( *cptr == wxT('\'') || *cptr == wxT('"') ) + quotechar = *cptr++; + + do + { + if ( *cptr == wxT('\\') && ! escaped ) + { + escaped = TRUE; + cptr++; + continue; + } + + // all other characters: + argument += *cptr++; + escaped = FALSE; + + // have we reached the end of the argument? + if ( (*cptr == quotechar && ! escaped) + || (quotechar == wxT('\0') && wxIsspace(*cptr)) + || *cptr == wxT('\0') ) + { + wxASSERT_MSG( argc < WXEXECUTE_NARGS, + wxT("too many arguments in wxExecute") ); + + argv[argc] = new wxChar[argument.length() + 1]; + wxStrcpy(argv[argc], argument.c_str()); + argc++; + + // if not at end of buffer, swallow last character: + if(*cptr) + cptr++; + + break; // done with this one, start over + } + } while(*cptr); + } while(*cptr); + argv[argc] = NULL; + + // do execute the command + long lRc = wxExecute(argv, sync, process); + + // clean up + argc = 0; + while( argv[argc] ) + delete [] argv[argc++]; + + return lRc; +} + +bool wxShell(const wxString& command) +{ + wxString cmd; + if ( !!command ) + cmd.Printf(wxT("xterm -e %s"), command.c_str()); + else + cmd = command; + + return wxExecute(cmd) != 0; +} + +#if wxUSE_GUI + +void wxHandleProcessTermination(wxEndProcessData *proc_data) +{ + int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid); + + // waitpid is POSIX so should be available everywhere, however on older + // systems wait() might be used instead in a loop (until the right pid + // terminates) + int status = 0; + int rc; + + // wait for child termination and if waitpid() was interrupted, try again + do + { + rc = waitpid(pid, &status, 0); + } + while ( rc == -1 && errno == EINTR ); + + + if( rc == -1 || ! (WIFEXITED(status) || WIFSIGNALED(status)) ) + { + wxLogSysError(_("Waiting for subprocess termination failed")); + /* AFAIK, this can only happen if something went wrong within + wxGTK, i.e. due to a race condition or some serious bug. + After having fixed the order of statements in + GTK_EndProcessDetector(). (KB) + */ + } + else + { + // notify user about termination if required + if (proc_data->process) + { + proc_data->process->OnTerminate(proc_data->pid, + WEXITSTATUS(status)); + } + // clean up + if ( proc_data->pid > 0 ) + { + delete proc_data; + } + else + { + // wxExecute() will know about it + proc_data->exitcode = status; + + proc_data->pid = 0; + } + } +} + +#endif // wxUSE_GUI + +#if wxUSE_GUI + #define WXUNUSED_UNLESS_GUI(p) p +#else + #define WXUNUSED_UNLESS_GUI(p) +#endif + +// New wxStream classes to clean up the data when the process terminates + +#if wxUSE_GUI +class wxProcessFileInputStream: public wxInputStream { + public: + wxProcessFileInputStream(int fd); + ~wxProcessFileInputStream(); + + protected: + size_t OnSysRead(void *buffer, size_t bufsize); + off_t OnSysSeek(off_t seek, wxSeekMode mode); + off_t OnSysTell() const; + + protected: + int m_fd; +}; + +class wxProcessFileOutputStream: public wxOutputStream { + public: + wxProcessFileOutputStream(int fd); + ~wxProcessFileOutputStream(); + + protected: + size_t OnSysWrite(const void *buffer, size_t bufsize); + off_t OnSysSeek(off_t seek, wxSeekMode mode); + off_t OnSysTell() const; + + protected: + int m_fd; +}; + +wxProcessFileInputStream::wxProcessFileInputStream(int fd) +{ + m_fd = fd; +} + +wxProcessFileInputStream::~wxProcessFileInputStream() +{ + close(m_fd); +} + +size_t wxProcessFileInputStream::OnSysRead(void *buffer, size_t bufsize) +{ + int ret; + + ret = read(m_fd, buffer, bufsize); + m_lasterror = wxSTREAM_NOERROR; + if (ret == 0) + m_lasterror = wxSTREAM_EOF; + if (ret == -1) { + m_lasterror = wxSTREAM_READ_ERROR; + ret = 0; + } + return ret; +} + +off_t wxProcessFileInputStream::OnSysSeek(off_t WXUNUSED(seek), + wxSeekMode WXUNUSED(mode)) +{ + return wxInvalidOffset; +} + +off_t wxProcessFileInputStream::OnSysTell() const +{ + return wxInvalidOffset; +} + + +wxProcessFileOutputStream::wxProcessFileOutputStream(int fd) +{ + m_fd = fd; +} + +wxProcessFileOutputStream::~wxProcessFileOutputStream() +{ + close(m_fd); +} + +size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize) +{ + int ret; + + ret = write(m_fd, buffer, bufsize); + m_lasterror = wxSTREAM_NOERROR; + if (ret == -1) { + m_lasterror = wxSTREAM_WRITE_ERROR; + ret = 0; + } + return ret; +} + +off_t wxProcessFileOutputStream::OnSysSeek(off_t WXUNUSED(seek), + wxSeekMode WXUNUSED(mode)) +{ + return wxInvalidOffset; +} + +off_t wxProcessFileOutputStream::OnSysTell() const +{ + return wxInvalidOffset; +} + +#endif + +long wxExecute(wxChar **argv, + bool sync, + wxProcess * WXUNUSED_UNLESS_GUI(process)) +{ + wxCHECK_MSG( *argv, 0, wxT("can't exec empty command") ); + +#if wxUSE_UNICODE + int mb_argc = 0; + char *mb_argv[WXEXECUTE_NARGS]; + + while (argv[mb_argc]) + { + wxWX2MBbuf mb_arg = wxConvertWX2MB(argv[mb_argc]); + mb_argv[mb_argc] = strdup(mb_arg); + mb_argc++; + } + mb_argv[mb_argc] = (char *) NULL; + + // this macro will free memory we used above + #define ARGS_CLEANUP \ + for ( mb_argc = 0; mb_argv[mb_argc]; mb_argc++ ) \ + free(mb_argv[mb_argc]) +#else // ANSI + // no need for cleanup + #define ARGS_CLEANUP + + wxChar **mb_argv = argv; +#endif // Unicode/ANSI + +#if wxUSE_GUI + // create pipes + int end_proc_detect[2]; + if (pipe(end_proc_detect) == -1) + { + wxLogSysError( _("Pipe creation failed") ); + + ARGS_CLEANUP; + + return 0; + } +#endif // wxUSE_GUI + +#if wxUSE_GUI + int in_pipe[2] = { -1, -1 }; + int out_pipe[2] = { -1, -1 }; + // Only asynchronous mode is interresting + if (!sync && process && process->NeedPipe()) + { + if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) + { + /* Free fds */ + close(end_proc_detect[0]); + close(end_proc_detect[1]); + wxLogSysError( _("Pipe creation failed (Console pipes)") ); + + ARGS_CLEANUP; + + return 0; + } + } +#endif // wxUSE_GUI + + // fork the process +#ifdef HAVE_VFORK + pid_t pid = vfork(); +#else + pid_t pid = fork(); +#endif + if (pid == -1) + { +#if wxUSE_GUI + close(end_proc_detect[0]); + close(end_proc_detect[1]); + close(in_pipe[0]); + close(in_pipe[1]); + close(out_pipe[0]); + close(out_pipe[1]); +#endif + wxLogSysError( _("Fork failed") ); + + ARGS_CLEANUP; + + return 0; + } + else if (pid == 0) + { +#if wxUSE_GUI + // we're in child + close(end_proc_detect[0]); // close reading side +#endif // wxUSE_GUI + + // These three lines close the open file descriptors to to avoid any + // input/output which might block the process or irritate the user. If + // one wants proper IO for the subprocess, the right thing to do is + // to start an xterm executing it. + if (sync == 0) + { + // leave stderr opened, it won't do any hurm + for ( int fd = 0; fd < FD_SETSIZE; fd++ ) + { +#if wxUSE_GUI + if ( fd == end_proc_detect[1] || fd == in_pipe[0] || fd == out_pipe[1] ) + continue; +#endif // wxUSE_GUI + + if ( fd != STDERR_FILENO ) + close(fd); + } + } + + // Fake a console by duplicating pipes +#if wxUSE_GUI + if (in_pipe[0] != -1) { + dup2(in_pipe[0], STDIN_FILENO); + dup2(out_pipe[1], STDOUT_FILENO); + close(in_pipe[0]); + close(out_pipe[1]); + } +#endif // wxUSE_GUI + +#if 0 + close(STDERR_FILENO); + + // some programs complain about stderr not being open, so redirect + // them: + open("/dev/null", O_RDONLY); // stdin + open("/dev/null", O_WRONLY); // stdout + open("/dev/null", O_WRONLY); // stderr +#endif + + execvp (*mb_argv, mb_argv); + + // there is no return after successful exec() + wxFprintf(stderr, _("Can't execute '%s'\n"), *argv); + + _exit(-1); + } + else + { +#if wxUSE_GUI + wxEndProcessData *data = new wxEndProcessData; + + ARGS_CLEANUP; + + if ( sync ) + { + wxASSERT_MSG( !process, wxT("wxProcess param ignored for sync exec") ); + data->process = NULL; + + // sync execution: indicate it by negating the pid + data->pid = -pid; + data->tag = wxAddProcessCallback(data, end_proc_detect[0]); + // we're in parent + close(end_proc_detect[1]); // close writing side + + // it will be set to 0 from GTK_EndProcessDetector + while (data->pid != 0) + wxYield(); + + int exitcode = data->exitcode; + + delete data; + + return exitcode; + } + else + { + // pipe initialization: construction of the wxStreams + if (process && process->NeedPipe()) { + // These two streams are relative to this process. + wxOutputStream *my_output_stream; + wxInputStream *my_input_stream; + + my_output_stream = new wxProcessFileOutputStream(in_pipe[1]); + my_input_stream = new wxProcessFileInputStream(out_pipe[0]); + close(in_pipe[0]); // close reading side + close(out_pipe[1]); // close writing side + + process->SetPipeStreams(my_input_stream, my_output_stream); + } + + // async execution, nothing special to do - caller will be + // notified about the process termination if process != NULL, data + // will be deleted in GTK_EndProcessDetector + data->process = process; + data->pid = pid; + data->tag = wxAddProcessCallback(data, end_proc_detect[0]); + // we're in parent + close(end_proc_detect[1]); // close writing side + + return pid; + } +#else // !wxUSE_GUI + wxASSERT_MSG( sync, wxT("async execution not supported yet") ); + + int exitcode = 0; + if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) ) + { + wxLogSysError(_("Waiting for subprocess termination failed")); + } + + return exitcode; +#endif // wxUSE_GUI + } + return 0; + + #undef ARGS_CLEANUP +} + +// ---------------------------------------------------------------------------- +// file and directory functions +// ---------------------------------------------------------------------------- + +const wxChar* wxGetHomeDir( wxString *home ) +{ + *home = wxGetUserHome( wxString() ); + if ( home->IsEmpty() ) + *home = wxT("/"); + + return home->c_str(); +} + +#if wxUSE_UNICODE +const wxMB2WXbuf wxGetUserHome( const wxString &user ) +#else // just for binary compatibility -- there is no 'const' here +char *wxGetUserHome( const wxString &user ) +#endif +{ + struct passwd *who = (struct passwd *) NULL; + + if ( !user ) + { + wxChar *ptr; + + if ((ptr = wxGetenv(wxT("HOME"))) != NULL) + { + return ptr; + } + if ((ptr = wxGetenv(wxT("USER"))) != NULL || (ptr = wxGetenv(wxT("LOGNAME"))) != NULL) + { + who = getpwnam(wxConvertWX2MB(ptr)); + } + + // We now make sure the the user exists! + if (who == NULL) + { + who = getpwuid(getuid()); + } + } + else + { + who = getpwnam (user.mb_str()); + } + + return wxConvertMB2WX(who ? who->pw_dir : 0); +} + +// ---------------------------------------------------------------------------- +// network and user id routines +// ---------------------------------------------------------------------------- + +// retrieve either the hostname or FQDN depending on platform (caller must +// check whether it's one or the other, this is why this function is for +// private use only) +static bool wxGetHostNameInternal(wxChar *buf, int sz) +{ + wxCHECK_MSG( buf, FALSE, wxT("NULL pointer in wxGetHostNameInternal") ); + + *buf = wxT('\0'); + + // we're using uname() which is POSIX instead of less standard sysinfo() +#if defined(HAVE_UNAME) + struct utsname uts; + bool ok = uname(&uts) != -1; + if ( ok ) + { + wxStrncpy(buf, wxConvertMB2WX(uts.nodename), sz - 1); + buf[sz] = wxT('\0'); + } +#elif defined(HAVE_GETHOSTNAME) + bool ok = gethostname(buf, sz) != -1; +#else // no uname, no gethostname + wxFAIL_MSG(wxT("don't know host name for this machine")); + + bool ok = FALSE; +#endif // uname/gethostname + + if ( !ok ) + { + wxLogSysError(_("Cannot get the hostname")); + } + + return ok; +} + +bool wxGetHostName(wxChar *buf, int sz) +{ + bool ok = wxGetHostNameInternal(buf, sz); + + if ( ok ) + { + // BSD systems return the FQDN, we only want the hostname, so extract + // it (we consider that dots are domain separators) + wxChar *dot = wxStrchr(buf, wxT('.')); + if ( dot ) + { + // nuke it + *dot = wxT('\0'); + } + } + + return ok; +} + +bool wxGetFullHostName(wxChar *buf, int sz) +{ + bool ok = wxGetHostNameInternal(buf, sz); + + if ( ok ) + { + if ( !wxStrchr(buf, wxT('.')) ) + { + struct hostent *host = gethostbyname(wxConvertWX2MB(buf)); + if ( !host ) + { + wxLogSysError(_("Cannot get the official hostname")); + + ok = FALSE; + } + else + { + // the canonical name + wxStrncpy(buf, wxConvertMB2WX(host->h_name), sz); + } + } + //else: it's already a FQDN (BSD behaves this way) + } + + return ok; +} + +bool wxGetUserId(wxChar *buf, int sz) +{ + struct passwd *who; + + *buf = wxT('\0'); + if ((who = getpwuid(getuid ())) != NULL) + { + wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1); + return TRUE; + } + + return FALSE; +} + +bool wxGetUserName(wxChar *buf, int sz) +{ + struct passwd *who; + + *buf = wxT('\0'); + if ((who = getpwuid (getuid ())) != NULL) + { + // pw_gecos field in struct passwd is not standard +#if HAVE_PW_GECOS + char *comma = strchr(who->pw_gecos, ','); + if (comma) + *comma = '\0'; // cut off non-name comment fields + wxStrncpy (buf, wxConvertMB2WX(who->pw_gecos), sz - 1); +#else // !HAVE_PW_GECOS + wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1); +#endif // HAVE_PW_GECOS/!HAVE_PW_GECOS + return TRUE; + } + + return FALSE; +} + +wxString wxGetOsDescription() +{ +#ifndef WXWIN_OS_DESCRIPTION + #error WXWIN_OS_DESCRIPTION should be defined in config.h by configure +#else + return WXWIN_OS_DESCRIPTION; +#endif +} + +// ---------------------------------------------------------------------------- +// error and debug output routines (deprecated, use wxLog) +// ---------------------------------------------------------------------------- + +void wxDebugMsg( const char *format, ... ) +{ + va_list ap; + va_start( ap, format ); + vfprintf( stderr, format, ap ); + fflush( stderr ); + va_end(ap); +} + +void wxError( const wxString &msg, const wxString &title ) +{ + wxFprintf( stderr, _("Error ") ); + if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) ); + if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) ); + wxFprintf( stderr, wxT(".\n") ); +} + +void wxFatalError( const wxString &msg, const wxString &title ) +{ + wxFprintf( stderr, _("Error ") ); + if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) ); + if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) ); + wxFprintf( stderr, wxT(".\n") ); + exit(3); // the same exit code as for abort() +} + -- 2.45.2