From c025a52704d7f98d47a39ff51bc3f4b9f4e13f23 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Mon, 15 Aug 2011 22:29:14 +0000 Subject: Re #1327, some fixes on the simple GUI app: - Removed timer usage in resizing window, window resizing can be done real-time now (see r3698). - Fixed linking problem on Windows platform: undefined 'main' function. - Fixed build problem on Mac, compiling .cpp file containing objective C/C++ codes with g++ needs '-ObjC++' flag. - Minor changes in vidgui, e.g: function/variable rename, cleaning up unused/junk lines. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3699 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/src/vidgui/vidgui.cpp | 16 ++- pjsip-apps/src/vidgui/vidgui.pro | 5 +- pjsip-apps/src/vidgui/vidwin.cpp | 302 +++++++++++++++++++++------------------ pjsip-apps/src/vidgui/vidwin.h | 20 +-- 4 files changed, 189 insertions(+), 154 deletions(-) (limited to 'pjsip-apps') diff --git a/pjsip-apps/src/vidgui/vidgui.cpp b/pjsip-apps/src/vidgui/vidgui.cpp index ca638634..4615ccdb 100644 --- a/pjsip-apps/src/vidgui/vidgui.cpp +++ b/pjsip-apps/src/vidgui/vidgui.cpp @@ -19,6 +19,10 @@ #include "vidgui.h" #include "vidwin.h" +#if defined(PJ_WIN32) +# define SDL_MAIN_HANDLED +#endif + #include #include #include @@ -50,6 +54,7 @@ MainWin::MainWin(QWidget *parent) MainWin::~MainWin() { + quit(); theInstance_ = NULL; } @@ -94,7 +99,7 @@ void MainWin::initLayout() connect(callButton_, SIGNAL(clicked()), this, SLOT(call())); connect(hangupButton_, SIGNAL(clicked()), this, SLOT(hangup())); connect(quitButton_, SIGNAL(clicked()), this, SLOT(quit())); - connect(this, SIGNAL(close()), this, SLOT(quit())); + //connect(this, SIGNAL(close()), this, SLOT(quit())); } void MainWin::quit() @@ -167,9 +172,13 @@ void MainWin::preview() } else { pjsua_vid_win_id wid; pjsua_vid_win_info wi; + pjsua_vid_preview_param pre_param; pj_status_t status; - status = pjsua_vid_preview_start(DEFAULT_CAP_DEV, NULL); + pj_bzero(&pre_param, sizeof(pre_param)); + pre_param.rend_id = DEFAULT_REND_DEV; + + status = pjsua_vid_preview_start(DEFAULT_CAP_DEV, &pre_param); if (status != PJ_SUCCESS) { char errmsg[PJ_ERR_MSG_SIZE]; pj_strerror(status, errmsg, sizeof(errmsg)); @@ -179,8 +188,7 @@ void MainWin::preview() wid = pjsua_vid_preview_get_win(DEFAULT_CAP_DEV); pjsua_vid_win_get_info(wid, &wi); - video_prev_= new VidWin(&wi.hwnd); - video_prev_->setMinimumSize(320,200); + video_prev_ = new VidWin(&wi.hwnd); vbox_left->addWidget(video_prev_, 1); previewButton_->setText(tr("Stop Preview")); diff --git a/pjsip-apps/src/vidgui/vidgui.pro b/pjsip-apps/src/vidgui/vidgui.pro index 5bf74ca8..eba5baf9 100644 --- a/pjsip-apps/src/vidgui/vidgui.pro +++ b/pjsip-apps/src/vidgui/vidgui.pro @@ -19,8 +19,11 @@ win32 { } else { LIBS += $$system(make -f pj-pkgconfig.mak ldflags) QMAKE_CXXFLAGS += $$system(make -f pj-pkgconfig.mak cflags) -} + macx { + QMAKE_CXXFLAGS += -ObjC++ + } +} TEMPLATE = app CONFIG += thread debug diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp index 8e207e4e..c8498242 100644 --- a/pjsip-apps/src/vidgui/vidwin.cpp +++ b/pjsip-apps/src/vidgui/vidwin.cpp @@ -1,222 +1,246 @@ #include "vidwin.h" +#include #define THIS_FILE "vidwin.cpp" -#define TIMER_EMBED 1 -#define TIMER_RESIZE 2 +#define TRACE_(...) PJ_LOG(4,(THIS_FILE, __VA_ARGS__)) -void VidWin::timer_cb(pj_timer_heap_t *timer_heap, - struct pj_timer_entry *entry) +VidWin::VidWin(const pjmedia_vid_dev_hwnd *hwnd_, + QWidget* parent, + Qt::WindowFlags f) : + QWidget(parent, f), orig_parent(NULL), + size_hint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) { - VidWin *vw = (VidWin*)entry->user_data; - - PJ_UNUSED_ARG(timer_heap); - - switch(entry->id) { - case TIMER_EMBED: - vw->embed(); - vw->resize(); - break; - case TIMER_RESIZE: - vw->resize(); - break; - default: - break; - } - - entry->id = 0; -} - - -VidWin::VidWin(pjmedia_vid_dev_hwnd *hwnd_, QWidget* parent, Qt::WindowFlags f) : - QWidget(parent, f), hwnd(*hwnd_) -{ -#if 0 - // A proof that QWidget::create() change window proc! - // And that will cause SDL rendering not working. - HWND h = (HWND)hwnd->info.win.hwnd; - LONG wl; - - wl = GetWindowLong(h, GWL_WNDPROC); - printf("%p old proc: %p\n", h, wl); - - create(WId(hwnd->info.win.hwnd), false, true); - printf("%p qwidgetwid: %p\n", h, winId()); - - wl = GetWindowLong(h, GWL_WNDPROC); - printf("%p new proc: %p\n", h, wl); -#endif - setAttribute(Qt::WA_NativeWindow); - setMinimumSize(320, 200); /* Make this widget a bit "lighter" */ - //setAttribute(Qt::WA_UpdatesDisabled); - //setAttribute(Qt::WA_PaintOnScreen); - //setAttribute(Qt::WA_NoSystemBackground); - //setAttribute(Qt::WA_PaintOutsidePaintEvent); - //setUpdatesEnabled(false); - - /* Schedule embed, as at this point widget initialization is not - * completely done yet (e.g: bad size). - */ - pj_timer_entry_init(&timer_entry, TIMER_EMBED, this, &timer_cb); - pj_time_val delay = {0, 100}; - pjsua_schedule_timer(&timer_entry, &delay); + setAttribute(Qt::WA_UpdatesDisabled); + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_PaintOutsidePaintEvent); + setUpdatesEnabled(false); + + pj_bzero(&hwnd, sizeof(hwnd)); + if (hwnd_) { + hwnd = *hwnd_; + } } VidWin::~VidWin() { - if (timer_entry.id) { - pjsua_cancel_timer(&timer_entry); - timer_entry.id = 0; - } + detach(); + pj_bzero(&hwnd, sizeof(hwnd)); + size_hint = QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + destroy(true, false); } - -void VidWin::resizeEvent(QResizeEvent*) +bool VidWin::event(QEvent *e) { - /* Resizing SDL window must be scheduled (via timer), - * as on Windows platform, the SDL resizing process - * will steal focus (SDL bug?). - */ - if (timer_entry.id && timer_entry.id != TIMER_RESIZE) - return; - - if (timer_entry.id == TIMER_RESIZE) - pjsua_cancel_timer(&timer_entry); - - timer_entry.id = TIMER_RESIZE; - timer_entry.cb = &timer_cb; - timer_entry.user_data = this; - - pj_time_val delay = {0, 300}; - pjsua_schedule_timer(&timer_entry, &delay); + switch(e->type()) { + case QEvent::Resize: + { + // revert to default size hint, make it resizable + setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); + // resize now + set_size(); + } + break; + case QEvent::ParentAboutToChange: + get_size(); + setFixedSize(size_hint); + break; + case QEvent::ParentChange: + { + get_size(); + /* + QRect qr = rect(); + if (qr.width() > size_hint.width()) + size_hint.setWidth(qr.width()); + if (qr.height() > size_hint.height()) + size_hint.setWidth(qr.height()); + */ + setFixedSize(size_hint); + attach(); + } + break; + default: + break; + } + + return QWidget::event(e); } /* Platform specific code */ -#if defined(PJ_WIN32) && !defined(PJ_WIN32_WINCE) +#if defined(_WIN32) && !defined(_WIN32_WINCE) #include -void VidWin::embed() +void VidWin::attach() { - /* Embed hwnd to widget */ - pj_assert(hwnd.type == PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS); - HWND h = (HWND)hwnd.info.win.hwnd; + if (!hwnd.info.win.hwnd) return; + + HWND w = (HWND)hwnd.info.win.hwnd; HWND new_parent = (HWND)winId(); + orig_parent = GetParent(w); + + SetParent(w, new_parent); + SetWindowLong(w, GWL_STYLE, WS_CHILD); + ShowWindow(w, SW_SHOWNOACTIVATE); + TRACE_("%p new parent handle = %p", w, new_parent); +} - //old_parent_hwnd.type = PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS; - //old_parent_hwnd.info.win.hwnd = GetParent(h); +void VidWin::detach() +{ + if (!hwnd.info.win.hwnd) return; - SetParent(h, new_parent); - SetWindowLong(h, GWL_STYLE, WS_CHILD); - ShowWindow(h, SW_SHOWNOACTIVATE); - PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", h, new_parent)); + HWND w = (HWND)hwnd.info.win.hwnd; + ShowWindow(w, SW_HIDE); + SetParent(w, (HWND)orig_parent); + TRACE_("%p revert parent handle to %p", w, orig_parent); } -void VidWin::resize() +void VidWin::set_size() { - /* Update position and size */ - HWND h = (HWND)hwnd.info.win.hwnd; + if (!hwnd.info.win.hwnd) return; + + HWND w = (HWND)hwnd.info.win.hwnd; QRect qr = rect(); - UINT swp_flag = SWP_SHOWWINDOW | SWP_NOACTIVATE; - SetWindowPos(h, HWND_TOP, 0, 0, qr.width(), qr.height(), swp_flag); - PJ_LOG(3, (THIS_FILE, "%p new size = %d x %d", h, qr.width(), qr.height())); + UINT swp_flag = SWP_NOACTIVATE; + SetWindowPos(w, HWND_TOP, 0, 0, qr.width(), qr.height(), swp_flag); + TRACE_("%p new size = %dx%d", w, qr.width(), qr.height()); } -#elif defined(PJ_DARWINOS) +void VidWin::get_size() +{ + if (!hwnd.info.win.hwnd) return; + + HWND w = (HWND)hwnd.info.win.hwnd; + RECT r; + if (GetWindowRect(w, &r)) + size_hint = QSize(r.right-r.left+1, r.bottom-r.top+1); + TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height()); +} + +#elif defined(__APPLE__) #import -void VidWin::embed() +void VidWin::attach() { + if (!hwnd.info.cocoa.window) return; + /* Embed hwnd to widget */ - pj_assert(hwnd.type != PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS); NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; NSWindow *parent = [(NSView*)winId() window]; + orig_parent = [w parentWindow]; //[w setStyleMask:NSBorderlessWindowMask]; + //Can't use this, as sometime the video window may not get reparented. //[w setParentWindow:parent]; + [parent addChildWindow:w ordered:NSWindowAbove]; - PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", w, parent)); + TRACE_("%p new parent handle = %p", w, parent); } -void VidWin::resize() +void VidWin::detach() { + if (!hwnd.info.cocoa.window) return; + + NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; + NSWindow *parent = [(NSView*)winId() window]; + [parent removeChildWindow:w]; +} + + +void VidWin::set_size() +{ + if (!hwnd.info.cocoa.window) return; + /* Update position and size */ NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; NSRect r; NSView* v = (NSView*)winId(); r = [v bounds]; - //PJ_LOG(3, (THIS_FILE, "before: (%d,%d) %dx%d", r.origin.x, r.origin.y, r.size.width, r.size.height)); r = [v convertRectToBase:r]; r.origin = [[v window] convertBaseToScreen:r.origin]; - //PJ_LOG(3, (THIS_FILE, "after: (%d,%d) %dx%d", r.origin.x, r.origin.y, r.size.width, r.size.height)); QRect qr = rect(); -/* - QPoint p = pos(); - QPoint pp = parentWidget()->pos(); - PJ_LOG(3, (THIS_FILE, "this pos: (%d,%d)", p.x(), p.y())); - PJ_LOG(3, (THIS_FILE, "parent pos: (%d,%d)", pp.x(), pp.y())); - - //qr.setTopLeft(mapToGlobal(qr.topLeft())); - r.origin.x = qr.x(); - r.origin.y = qr.y(); - r.size.width = qr.width(); - r.size.height = qr.height(); - //r.origin = [w convertBaseToScreen:r.origin]; -*/ [w setFrame:r display:NO]; - PJ_LOG(3, (THIS_FILE, "%p new size = %d x %d", w, qr.width(), qr.height())); + TRACE_("%p new size = %dx%d", w, qr.width(), qr.height()); } -#elif defined(PJ_LINUX) +void VidWin::get_size() +{ + if (!hwnd.info.cocoa.window) return; + + NSWindow *w = (NSWindow*)hwnd.info.cocoa.window; + + size_hint = QSize(300, 200); + + TRACE_("%p size = %dx%d", 0, size_hint.width(), size_hint.height()); +} + + +#elif defined(linux) || defined(__linux) #include -//#include +#include +#include +#include -void VidWin::embed() +void VidWin::attach() { + if (!hwnd.info.x11.window) return; + /* Embed hwnd to widget */ - pj_assert(hwnd.type != PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS); - Display *d = (Display*)hwnd.info.x11.display; - //Display *d = QX11Info::display(); + + // Use Qt X11 display here, using window creator X11 display may cause + // the window failing to embed to this QWidget. + //Display *d = (Display*)hwnd.info.x11.display; + Display *d = QX11Info::display(); Window w = (Window)hwnd.info.x11.window; Window parent = (Window)this->winId(); + int err = XReparentWindow(d, w, parent, 0, 0); + TRACE_("%p new parent handle = %p, err = %d", + (void*)w,(void*)parent, err); +} - XSetWindowBorderWidth(d, w, 0); - int err = XReparentWindow(d, w, parent, 0, 0); - PJ_LOG(3, (THIS_FILE, "XReparentWindow() err = %d", err)); - //XRaiseWindow(d, w); - //XMapSubwindows(d, parent); - //XMapWindow(d, parent); - //XMapWindow(d, w); - //XSync(d, False); - - PJ_LOG(3, (THIS_FILE, "[%p,%p] parent handle = %p", d, w, parent)); +void VidWin::detach() +{ } -void VidWin::resize() +void VidWin::set_size() { + if (!hwnd.info.x11.window) return; + /* Update position and size */ - Display *d = (Display*)hwnd.info.x11.display; + Display *d = QX11Info::display(); Window w = (Window)hwnd.info.x11.window; QRect qr = rect(); - //XResizeWindow(d, w, qr.width(), qr.height()); - XMoveResizeWindow(d, w, 0, 0, qr.width(), qr.height()); - PJ_LOG(3, (THIS_FILE, "[%p,%p] new size = %d x %d", d, w, qr.width(), qr.height())); - //XSync(d, False); - XFlush(d); + int err = XResizeWindow(d, w, qr.width(), qr.height()); + TRACE_("[%p,%p] new size = %dx%d, err = %d", + (void*)d, (void*)w, qr.width(), qr.height(), err); +} + +void VidWin::get_size() +{ + if (!hwnd.info.x11.window) return; + + Display *d = QX11Info::display(); + Window w = (Window)hwnd.info.x11.window; + + XWindowAttributes attr; + XGetWindowAttributes(d, w, &attr); + size_hint = QSize(attr.width, attr.height); + TRACE_("%p size = %dx%d", w, size_hint.width(), size_hint.height()); } #endif diff --git a/pjsip-apps/src/vidgui/vidwin.h b/pjsip-apps/src/vidgui/vidwin.h index 629a960e..de6e2753 100644 --- a/pjsip-apps/src/vidgui/vidwin.h +++ b/pjsip-apps/src/vidgui/vidwin.h @@ -9,25 +9,25 @@ class VidWin : public QWidget Q_OBJECT public: - // hwnd Handle of the video rendering window. - VidWin(pjmedia_vid_dev_hwnd *hwnd = NULL, + VidWin(const pjmedia_vid_dev_hwnd *hwnd, QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~VidWin(); + QSize sizeHint() const { return size_hint; } protected: - void resizeEvent(QResizeEvent *e); + virtual bool event(QEvent *e); private: pjmedia_vid_dev_hwnd hwnd; - //pjmedia_vid_dev_hwnd old_parent_hwnd; - pj_timer_entry timer_entry; + void *orig_parent; + QSize size_hint; - static void timer_cb(pj_timer_heap_t *timer_heap, - struct pj_timer_entry *entry); - - void embed(); - void resize(); + void attach(); + void detach(); + void set_size(); + void get_size(); }; #endif + -- cgit v1.2.3