From 7ff94efc1c42866646b688b3dbc8e42fc877ae71 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Mon, 1 Aug 2011 12:57:45 +0000 Subject: Re #1327: Very early version of simple video GUI, built on Qt, should run on win/lin/mac. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3686 74dad513-b988-da41-8d7b-12977e46ad98 --- pjsip-apps/build/vidgui.vcproj | 207 ++++++++++++ pjsip-apps/src/vidgui/Makefile | 271 ++++++++++++++++ pjsip-apps/src/vidgui/moc_vidgui.cpp | 86 +++++ pjsip-apps/src/vidgui/moc_vidwin.cpp | 69 ++++ pjsip-apps/src/vidgui/vidgui.cpp | 592 +++++++++++++++++++++++++++++++++++ pjsip-apps/src/vidgui/vidgui.h | 93 ++++++ pjsip-apps/src/vidgui/vidwin.cpp | 223 +++++++++++++ pjsip-apps/src/vidgui/vidwin.h | 33 ++ 8 files changed, 1574 insertions(+) create mode 100644 pjsip-apps/build/vidgui.vcproj create mode 100644 pjsip-apps/src/vidgui/Makefile create mode 100644 pjsip-apps/src/vidgui/moc_vidgui.cpp create mode 100644 pjsip-apps/src/vidgui/moc_vidwin.cpp create mode 100644 pjsip-apps/src/vidgui/vidgui.cpp create mode 100644 pjsip-apps/src/vidgui/vidgui.h create mode 100644 pjsip-apps/src/vidgui/vidwin.cpp create mode 100644 pjsip-apps/src/vidgui/vidwin.h (limited to 'pjsip-apps') diff --git a/pjsip-apps/build/vidgui.vcproj b/pjsip-apps/build/vidgui.vcproj new file mode 100644 index 00000000..31cf7db8 --- /dev/null +++ b/pjsip-apps/build/vidgui.vcproj @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pjsip-apps/src/vidgui/Makefile b/pjsip-apps/src/vidgui/Makefile new file mode 100644 index 00000000..3efca14e --- /dev/null +++ b/pjsip-apps/src/vidgui/Makefile @@ -0,0 +1,271 @@ +############################################################################# +# Makefile for building: vidgui.app/Contents/MacOS/vidgui +# Generated by qmake (2.01a) (Qt 4.7.3) on: Fri Jul 29 19:21:47 2011 +# Project: vidgui.pro +# Template: app +# Command: /usr/bin/qmake -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile vidgui.pro +############################################################################# + +PJBASE=/Users/nanang/project/pj +include $(PJBASE)/build.mak + +####### Compiler, tools and options + +CC = gcc +CXX = g++ +DEFINES = -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED +CFLAGS = -ObjC -pipe -g -gdwarf-2 -Wall -W $(DEFINES) $(PJ_CFLAGS) +CXXFLAGS = -ObjC++ -pipe -g -gdwarf-2 -Wall -W $(DEFINES) $(PJ_CFLAGS) +INCPATH = -I/usr/local/Qt4.7/mkspecs/macx-g++ -I. -I/Library/Frameworks/QtCore.framework/Versions/4/Headers -I/usr/include/QtCore -I/Library/Frameworks/QtGui.framework/Versions/4/Headers -I/usr/include/QtGui -I/usr/include -I. -I. -F/Library/Frameworks +LINK = g++ +LFLAGS = -headerpad_max_install_names +LIBS = $(SUBLIBS) $(PJ_LDFLAGS) $(PJ_LDLIBS) -F/Library/Frameworks -L/Library/Frameworks -framework QtGui -framework QtCore +AR = ar cq +RANLIB = ranlib -s +QMAKE = /usr/bin/qmake +TAR = tar -cf +COMPRESS = gzip -9f +COPY = cp -f +SED = sed +COPY_FILE = cp -f +COPY_DIR = cp -f -R +STRIP = +INSTALL_FILE = $(COPY_FILE) +INSTALL_DIR = $(COPY_DIR) +INSTALL_PROGRAM = $(COPY_FILE) +DEL_FILE = rm -f +SYMLINK = ln -f -s +DEL_DIR = rmdir +MOVE = mv -f +CHK_DIR_EXISTS= test -d +MKDIR = mkdir -p +export MACOSX_DEPLOYMENT_TARGET = 10.4 + +####### Output directory + +OBJECTS_DIR = ./ + +####### Files + +SOURCES = vidgui.cpp \ + vidwin.cpp moc_vidgui.cpp \ + moc_vidwin.cpp +OBJECTS = vidgui.o \ + vidwin.o \ + moc_vidgui.o \ + moc_vidwin.o +DIST = /usr/local/Qt4.7/mkspecs/common/unix.conf \ + /usr/local/Qt4.7/mkspecs/common/mac.conf \ + /usr/local/Qt4.7/mkspecs/common/mac-g++.conf \ + /usr/local/Qt4.7/mkspecs/qconfig.pri \ + /usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri \ + /usr/local/Qt4.7/mkspecs/features/qt_functions.prf \ + /usr/local/Qt4.7/mkspecs/features/qt_config.prf \ + /usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf \ + /usr/local/Qt4.7/mkspecs/features/default_pre.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf \ + /usr/local/Qt4.7/mkspecs/features/debug.prf \ + /usr/local/Qt4.7/mkspecs/features/default_post.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/default_post.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf \ + /usr/local/Qt4.7/mkspecs/features/warn_on.prf \ + /usr/local/Qt4.7/mkspecs/features/qt.prf \ + /usr/local/Qt4.7/mkspecs/features/unix/thread.prf \ + /usr/local/Qt4.7/mkspecs/features/moc.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/rez.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/sdk.prf \ + /usr/local/Qt4.7/mkspecs/features/resources.prf \ + /usr/local/Qt4.7/mkspecs/features/uic.prf \ + /usr/local/Qt4.7/mkspecs/features/yacc.prf \ + /usr/local/Qt4.7/mkspecs/features/lex.prf \ + /usr/local/Qt4.7/mkspecs/features/include_source_dir.prf \ + vidgui.pro +QMAKE_TARGET = vidgui +DESTDIR = +TARGET = vidgui.app/Contents/MacOS/vidgui + +####### Custom Compiler Variables +QMAKE_COMP_QMAKE_OBJECTIVE_CFLAGS = -pipe \ + -g \ + -gdwarf-2 \ + -Wall \ + -W + + +first: all +####### Implicit rules + +.SUFFIXES: .o .c .cpp .cc .cxx .C + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cc.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.cxx.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.C.o: + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o "$@" "$<" + +.c.o: + $(CC) -c $(CFLAGS) $(INCPATH) -o "$@" "$<" + +####### Build rules + +all: Makefile vidgui.app/Contents/PkgInfo vidgui.app/Contents/Resources/empty.lproj vidgui.app/Contents/Info.plist $(TARGET) + +$(TARGET): $(OBJECTS) + @$(CHK_DIR_EXISTS) vidgui.app/Contents/MacOS/ || $(MKDIR) vidgui.app/Contents/MacOS/ + $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS) + +Makefile: vidgui.pro /usr/local/Qt4.7/mkspecs/macx-g++/qmake.conf /usr/local/Qt4.7/mkspecs/common/unix.conf \ + /usr/local/Qt4.7/mkspecs/common/mac.conf \ + /usr/local/Qt4.7/mkspecs/common/mac-g++.conf \ + /usr/local/Qt4.7/mkspecs/qconfig.pri \ + /usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri \ + /usr/local/Qt4.7/mkspecs/features/qt_functions.prf \ + /usr/local/Qt4.7/mkspecs/features/qt_config.prf \ + /usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf \ + /usr/local/Qt4.7/mkspecs/features/default_pre.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf \ + /usr/local/Qt4.7/mkspecs/features/debug.prf \ + /usr/local/Qt4.7/mkspecs/features/default_post.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/default_post.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf \ + /usr/local/Qt4.7/mkspecs/features/warn_on.prf \ + /usr/local/Qt4.7/mkspecs/features/qt.prf \ + /usr/local/Qt4.7/mkspecs/features/unix/thread.prf \ + /usr/local/Qt4.7/mkspecs/features/moc.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/rez.prf \ + /usr/local/Qt4.7/mkspecs/features/mac/sdk.prf \ + /usr/local/Qt4.7/mkspecs/features/resources.prf \ + /usr/local/Qt4.7/mkspecs/features/uic.prf \ + /usr/local/Qt4.7/mkspecs/features/yacc.prf \ + /usr/local/Qt4.7/mkspecs/features/lex.prf \ + /usr/local/Qt4.7/mkspecs/features/include_source_dir.prf \ + /Library/Frameworks/QtGui.framework/QtGui.prl \ + /Library/Frameworks/QtCore.framework/QtCore.prl + $(QMAKE) -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile vidgui.pro +/usr/local/Qt4.7/mkspecs/common/unix.conf: +/usr/local/Qt4.7/mkspecs/common/mac.conf: +/usr/local/Qt4.7/mkspecs/common/mac-g++.conf: +/usr/local/Qt4.7/mkspecs/qconfig.pri: +/usr/local/Qt4.7/mkspecs/modules/qt_webkit_version.pri: +/usr/local/Qt4.7/mkspecs/features/qt_functions.prf: +/usr/local/Qt4.7/mkspecs/features/qt_config.prf: +/usr/local/Qt4.7/mkspecs/features/exclusive_builds.prf: +/usr/local/Qt4.7/mkspecs/features/default_pre.prf: +/usr/local/Qt4.7/mkspecs/features/mac/default_pre.prf: +/usr/local/Qt4.7/mkspecs/features/mac/dwarf2.prf: +/usr/local/Qt4.7/mkspecs/features/debug.prf: +/usr/local/Qt4.7/mkspecs/features/default_post.prf: +/usr/local/Qt4.7/mkspecs/features/mac/default_post.prf: +/usr/local/Qt4.7/mkspecs/features/mac/objective_c.prf: +/usr/local/Qt4.7/mkspecs/features/warn_on.prf: +/usr/local/Qt4.7/mkspecs/features/qt.prf: +/usr/local/Qt4.7/mkspecs/features/unix/thread.prf: +/usr/local/Qt4.7/mkspecs/features/moc.prf: +/usr/local/Qt4.7/mkspecs/features/mac/rez.prf: +/usr/local/Qt4.7/mkspecs/features/mac/sdk.prf: +/usr/local/Qt4.7/mkspecs/features/resources.prf: +/usr/local/Qt4.7/mkspecs/features/uic.prf: +/usr/local/Qt4.7/mkspecs/features/yacc.prf: +/usr/local/Qt4.7/mkspecs/features/lex.prf: +/usr/local/Qt4.7/mkspecs/features/include_source_dir.prf: +/Library/Frameworks/QtGui.framework/QtGui.prl: +/Library/Frameworks/QtCore.framework/QtCore.prl: +qmake: FORCE + @$(QMAKE) -spec /usr/local/Qt4.7/mkspecs/macx-g++ -o Makefile vidgui.pro + +vidgui.app/Contents/PkgInfo: + @$(CHK_DIR_EXISTS) vidgui.app/Contents || $(MKDIR) vidgui.app/Contents + @$(DEL_FILE) vidgui.app/Contents/PkgInfo + @echo "APPL????" >vidgui.app/Contents/PkgInfo +vidgui.app/Contents/Resources/empty.lproj: + @$(CHK_DIR_EXISTS) vidgui.app/Contents/Resources || $(MKDIR) vidgui.app/Contents/Resources + @touch vidgui.app/Contents/Resources/empty.lproj + +vidgui.app/Contents/Info.plist: + @$(CHK_DIR_EXISTS) vidgui.app/Contents || $(MKDIR) vidgui.app/Contents + @$(DEL_FILE) vidgui.app/Contents/Info.plist + @sed -e "s,@ICON@,,g" -e "s,@EXECUTABLE@,vidgui,g" -e "s,@TYPEINFO@,????,g" /usr/local/Qt4.7/mkspecs/macx-g++/Info.plist.app >vidgui.app/Contents/Info.plist +dist: + @$(CHK_DIR_EXISTS) .tmp/vidgui1.0.0 || $(MKDIR) .tmp/vidgui1.0.0 + $(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/vidgui1.0.0/ && $(COPY_FILE) --parents vidgui.h vidwin.h .tmp/vidgui1.0.0/ && $(COPY_FILE) --parents vidgui.cpp vidwin.cpp .tmp/vidgui1.0.0/ && (cd `dirname .tmp/vidgui1.0.0` && $(TAR) vidgui1.0.0.tar vidgui1.0.0 && $(COMPRESS) vidgui1.0.0.tar) && $(MOVE) `dirname .tmp/vidgui1.0.0`/vidgui1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/vidgui1.0.0 + + +clean:compiler_clean + -$(DEL_FILE) $(OBJECTS) + -$(DEL_FILE) *~ core *.core + + +####### Sub-libraries + +distclean: clean + -$(DEL_FILE) -r vidgui.app + -$(DEL_FILE) Makefile + + +check: first + +mocclean: compiler_moc_header_clean compiler_moc_source_clean + +mocables: compiler_moc_header_make_all compiler_moc_source_make_all + +compiler_objective_c_make_all: +compiler_objective_c_clean: +compiler_moc_header_make_all: moc_vidgui.cpp moc_vidwin.cpp +compiler_moc_header_clean: + -$(DEL_FILE) moc_vidgui.cpp moc_vidwin.cpp +moc_vidgui.cpp: vidgui.h + /Developer/Tools/Qt/moc $(DEFINES) $(INCPATH) -D__APPLE__ -D__GNUC__ vidgui.h -o moc_vidgui.cpp + +moc_vidwin.cpp: vidwin.h + /Developer/Tools/Qt/moc $(DEFINES) $(INCPATH) -D__APPLE__ -D__GNUC__ vidwin.h -o moc_vidwin.cpp + +compiler_rcc_make_all: +compiler_rcc_clean: +compiler_image_collection_make_all: qmake_image_collection.cpp +compiler_image_collection_clean: + -$(DEL_FILE) qmake_image_collection.cpp +compiler_moc_source_make_all: +compiler_moc_source_clean: +compiler_rez_source_make_all: +compiler_rez_source_clean: +compiler_uic_make_all: +compiler_uic_clean: +compiler_yacc_decl_make_all: +compiler_yacc_decl_clean: +compiler_yacc_impl_make_all: +compiler_yacc_impl_clean: +compiler_lex_make_all: +compiler_lex_clean: +compiler_clean: compiler_moc_header_clean + +####### Compile + +vidgui.o: vidgui.cpp vidgui.h \ + vidwin.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o vidgui.o vidgui.cpp + +vidwin.o: vidwin.cpp vidwin.h + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o vidwin.o vidwin.cpp + +moc_vidgui.o: moc_vidgui.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_vidgui.o moc_vidgui.cpp + +moc_vidwin.o: moc_vidwin.cpp + $(CXX) -c $(CXXFLAGS) $(INCPATH) -o moc_vidwin.o moc_vidwin.cpp + +####### Install + +install: FORCE + +uninstall: FORCE + +FORCE: + diff --git a/pjsip-apps/src/vidgui/moc_vidgui.cpp b/pjsip-apps/src/vidgui/moc_vidgui.cpp new file mode 100644 index 00000000..0691312d --- /dev/null +++ b/pjsip-apps/src/vidgui/moc_vidgui.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'vidgui.h' +** +** Created: Fri Jul 29 21:57:30 2011 +** by: The Qt Meta Object Compiler version 62 (Qt 4.7.3) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "vidgui.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'vidgui.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.7.3. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_MainWin[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 4, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: signature, parameters, type, tag, flags + 9, 8, 8, 8, 0x0a, + 19, 8, 8, 8, 0x0a, + 26, 8, 8, 8, 0x0a, + 35, 8, 8, 8, 0x0a, + + 0 // eod +}; + +static const char qt_meta_stringdata_MainWin[] = { + "MainWin\0\0preview()\0call()\0hangup()\0" + "quit()\0" +}; + +const QMetaObject MainWin::staticMetaObject = { + { &QWidget::staticMetaObject, qt_meta_stringdata_MainWin, + qt_meta_data_MainWin, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &MainWin::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *MainWin::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *MainWin::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_MainWin)) + return static_cast(const_cast< MainWin*>(this)); + return QWidget::qt_metacast(_clname); +} + +int MainWin::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + switch (_id) { + case 0: preview(); break; + case 1: call(); break; + case 2: hangup(); break; + case 3: quit(); break; + default: ; + } + _id -= 4; + } + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/pjsip-apps/src/vidgui/moc_vidwin.cpp b/pjsip-apps/src/vidgui/moc_vidwin.cpp new file mode 100644 index 00000000..1c3725a8 --- /dev/null +++ b/pjsip-apps/src/vidgui/moc_vidwin.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'vidwin.h' +** +** Created: Fri Jul 29 21:57:33 2011 +** by: The Qt Meta Object Compiler version 62 (Qt 4.7.3) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "vidwin.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'vidwin.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.7.3. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_VidWin[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_VidWin[] = { + "VidWin\0" +}; + +const QMetaObject VidWin::staticMetaObject = { + { &QWidget::staticMetaObject, qt_meta_stringdata_VidWin, + qt_meta_data_VidWin, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &VidWin::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *VidWin::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *VidWin::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_VidWin)) + return static_cast(const_cast< VidWin*>(this)); + return QWidget::qt_metacast(_clname); +} + +int VidWin::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/pjsip-apps/src/vidgui/vidgui.cpp b/pjsip-apps/src/vidgui/vidgui.cpp new file mode 100644 index 00000000..ce1c89b1 --- /dev/null +++ b/pjsip-apps/src/vidgui/vidgui.cpp @@ -0,0 +1,592 @@ +/* $Id$ */ +/* + * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "vidgui.h" +#include "vidwin.h" + +#include + +#define LOG_FILE "vidgui.log" + +#define SIP_DOMAIN NULL +//#define SIP_DOMAIN "pjsip.org" +#define SIP_USERNAME "vidgui" +#define SIP_PASSWORD "secret" +#define SIP_PORT 5060 + +//#define DEFAULT_CAP_DEV PJMEDIA_VID_DEFAULT_CAPTURE_DEV +#define DEFAULT_CAP_DEV 1 +#define DEFAULT_REND_DEV PJMEDIA_VID_DEFAULT_RENDER_DEV + +MainWin *MainWin::theInstance_; + +MainWin::MainWin(QWidget *parent) +: QWidget(parent), accountId_(-1), currentCall_(-1), + preview_on(false), video_(NULL), video_prev_(NULL) +{ + theInstance_ = this; + + initLayout(); + onCallReleased(); +} + +MainWin::~MainWin() +{ + theInstance_ = NULL; +} + +MainWin *MainWin::instance() +{ + return theInstance_; +} + +void MainWin::initLayout() +{ + //statusBar_ = new QStatusBar(this); + + /* main layout */ + QHBoxLayout *hbox_main = new QHBoxLayout; + //QVBoxLayout *vbox_left = new QVBoxLayout; + vbox_left = new QVBoxLayout; + QVBoxLayout *vbox_right = new QVBoxLayout; + hbox_main->addLayout(vbox_left); + hbox_main->addLayout(vbox_right); + + /* Left pane */ + QHBoxLayout *hbox_url = new QHBoxLayout; + hbox_url->addWidget(new QLabel(tr("Url:"))); + hbox_url->addWidget(url_=new QLineEdit(tr("sip:")), 1); + vbox_left->addLayout(hbox_url); + + /* Right pane */ + vbox_right->addWidget((localUri_ = new QLabel)); + vbox_right->addWidget((previewButton_=new QPushButton(tr("Start Preview")))); + vbox_right->addWidget((callButton_=new QPushButton(tr("Call")))); + vbox_right->addWidget((hangupButton_=new QPushButton(tr("Hangup")))); + vbox_right->addWidget((quitButton_=new QPushButton(tr("Quit")))); + + /* Outest layout */ + QVBoxLayout *vbox_outest = new QVBoxLayout; + vbox_outest->addLayout(hbox_main); + vbox_outest->addWidget((statusBar_ = new QLabel)); + + setLayout(vbox_outest); + + connect(previewButton_, SIGNAL(clicked()), this, SLOT(preview())); + 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())); +} + +void MainWin::quit() +{ + pjsua_destroy(); + qApp->quit(); +} + +void MainWin::showStatus(const char *msg) +{ + //statusBar_->showMessage(msg); + statusBar_->setText(msg); + PJ_LOG(3,("vidgui.cpp", "%s", msg)); +} + +void MainWin::showError(const char *title, pj_status_t status) +{ + char errmsg[PJ_ERR_MSG_SIZE]; + char errline[120]; + + pj_strerror(status, errmsg, sizeof(errmsg)); + snprintf(errline, sizeof(errline), "%s error: %s", title, errmsg); + showStatus(errline); +} + +void MainWin::onNewCall(pjsua_call_id cid, bool incoming) +{ + pjsua_call_info ci; + + pj_assert(currentCall_ == -1); + currentCall_ = cid; + + pjsua_call_get_info(cid, &ci); + url_->setText(ci.remote_info.ptr); + url_->setEnabled(false); + hangupButton_->setEnabled(true); + + if (incoming) { + callButton_->setText(tr("Answer")); + callButton_->setEnabled(true); + } else { + callButton_->setEnabled(false); + } + + //video_->setText(ci.remote_contact.ptr); + //video_->setWindowTitle(ci.remote_contact.ptr); +} + +void MainWin::onCallReleased() +{ + url_->setEnabled(true); + callButton_->setEnabled(true); + callButton_->setText(tr("Call")); + hangupButton_->setEnabled(false); + currentCall_ = -1; + + delete video_; + video_ = NULL; +} + +void MainWin::preview() +{ + if (preview_on) { + delete video_prev_; + video_prev_ = NULL; + + pjsua_vid_preview_stop(DEFAULT_CAP_DEV); + + previewButton_->setText(tr("Start Preview")); + } else { + pjsua_vid_win_id wid; + pjsua_vid_win_info wi; + + pjsua_vid_preview_start(DEFAULT_CAP_DEV, NULL); + 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); + vbox_left->addWidget(video_prev_, 1); + + previewButton_->setText(tr("Stop Preview")); + } + preview_on = !preview_on; +} + + +void MainWin::call() +{ + if (callButton_->text() == "Answer") { + pj_assert(currentCall_ != -1); + pjsua_call_answer(currentCall_, 200, NULL, NULL); + callButton_->setEnabled(false); + } else { + pj_status_t status; + QString dst = url_->text(); + const char *uri = dst.toAscii().data(); + pj_str_t uri2 = pj_str((char*)uri); + + pj_assert(currentCall_ == -1); + + status = pjsua_call_make_call(accountId_, &uri2, 0, + NULL, NULL, ¤tCall_); + if (status != PJ_SUCCESS) { + showError("make call", status); + return; + } + } +} + +void MainWin::hangup() +{ + pj_assert(currentCall_ != -1); + //pjsua_call_hangup(currentCall_, PJSIP_SC_BUSY_HERE, NULL, NULL); + pjsua_call_hangup_all(); + onCallReleased(); +} + + +void MainWin::init_video_window() +{ + pjsua_call_info ci; + unsigned i; + + if (currentCall_ == -1) + return; + + pjsua_call_get_info(currentCall_, &ci); + for (i = 0; i < ci.media_cnt; ++i) { + if ((ci.media[i].type == PJMEDIA_TYPE_VIDEO) && + (ci.media[i].dir & PJMEDIA_DIR_DECODING)) + { + pjsua_vid_win_info wi; + pjsua_vid_win_get_info(ci.media[i].stream.vid.win_in, &wi); + + video_= new VidWin(&wi.hwnd); + vbox_left->addWidget(video_, 1); + + break; + } + } +} + +void MainWin::on_reg_state(pjsua_acc_id acc_id) +{ + pjsua_acc_info info; + + pjsua_acc_get_info(acc_id, &info); + + char reg_status[80]; + char status[120]; + + if (!info.has_registration) { + pj_ansi_snprintf(reg_status, sizeof(reg_status), "%.*s", + (int)info.status_text.slen, + info.status_text.ptr); + + } else { + pj_ansi_snprintf(reg_status, sizeof(reg_status), + "%d/%.*s (expires=%d)", + info.status, + (int)info.status_text.slen, + info.status_text.ptr, + info.expires); + + } + + snprintf(status, sizeof(status), + "%.*s: %s\n", + (int)info.acc_uri.slen, info.acc_uri.ptr, + reg_status); + showStatus(status); +} + +void MainWin::on_call_state(pjsua_call_id call_id, pjsip_event *e) +{ + pjsua_call_info ci; + + PJ_UNUSED_ARG(e); + + pjsua_call_get_info(call_id, &ci); + + if (currentCall_ == -1 && ci.state < PJSIP_INV_STATE_DISCONNECTED) { + onNewCall(call_id, false); + } + + char status[80]; + if (ci.state == PJSIP_INV_STATE_DISCONNECTED) { + snprintf(status, sizeof(status), "Call is %s (%s)", + ci.state_text.ptr, + ci.last_status_text.ptr); + showStatus(status); + onCallReleased(); + } else { + snprintf(status, sizeof(status), "Call is %s", pjsip_inv_state_name(ci.state)); + showStatus(status); + } +} + +void MainWin::on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, + pjsip_rx_data *rdata) +{ + PJ_UNUSED_ARG(acc_id); + PJ_UNUSED_ARG(rdata); + + if (currentCall_ != -1) { + pjsua_call_answer(call_id, PJSIP_SC_BUSY_HERE, NULL, NULL); + return; + } + + onNewCall(call_id, true); + + pjsua_call_info ci; + char status[80]; + + pjsua_call_get_info(call_id, &ci); + snprintf(status, sizeof(status), "Incoming call from %.*s", + (int)ci.remote_info.slen, ci.remote_info.ptr); + showStatus(status); +} + +void MainWin::on_call_media_state(pjsua_call_id call_id) +{ + pjsua_call_info ci; + + pjsua_call_get_info(call_id, &ci); + + for (unsigned i=0; ion_reg_state(acc_id); +} + +static void on_call_state(pjsua_call_id call_id, pjsip_event *e) +{ + MainWin::instance()->on_call_state(call_id, e); +} + +static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, + pjsip_rx_data *rdata) +{ + MainWin::instance()->on_incoming_call(acc_id, call_id, rdata); +} + +static void on_call_media_state(pjsua_call_id call_id) +{ + MainWin::instance()->on_call_media_state(call_id); +} + +// +// initStack() +// +bool MainWin::initStack() +{ + pj_status_t status; + + //showStatus("Creating stack.."); + status = pjsua_create(); + if (status != PJ_SUCCESS) { + showError("pjsua_create", status); + return false; + } + + showStatus("Initializing stack.."); + + pjsua_config ua_cfg; + pjsua_config_default(&ua_cfg); + pjsua_callback ua_cb; + pj_bzero(&ua_cb, sizeof(ua_cb)); + ua_cfg.cb.on_reg_state = &::on_reg_state; + ua_cfg.cb.on_call_state = &::on_call_state; + ua_cfg.cb.on_incoming_call = &::on_incoming_call; + ua_cfg.cb.on_call_media_state = &::on_call_media_state; + + pjsua_logging_config log_cfg; + pjsua_logging_config_default(&log_cfg); + log_cfg.log_filename = pj_str((char*)LOG_FILE); + + pjsua_media_config med_cfg; + pjsua_media_config_default(&med_cfg); + + status = pjsua_init(&ua_cfg, &log_cfg, &med_cfg); + if (status != PJ_SUCCESS) { + showError("pjsua_init", status); + goto on_error; + } + + // + // Create UDP and TCP transports + // + pjsua_transport_config udp_cfg; + pjsua_transport_id udp_id; + pjsua_transport_config_default(&udp_cfg); + udp_cfg.port = SIP_PORT; + + status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, + &udp_cfg, &udp_id); + if (status != PJ_SUCCESS) { + showError("UDP transport creation", status); + goto on_error; + } + + pjsua_transport_info udp_info; + status = pjsua_transport_get_info(udp_id, &udp_info); + if (status != PJ_SUCCESS) { + showError("UDP transport info", status); + goto on_error; + } + + pjsua_transport_config tcp_cfg; + pjsua_transport_config_default(&tcp_cfg); + tcp_cfg.port = 0; + + status = pjsua_transport_create(PJSIP_TRANSPORT_TCP, + &tcp_cfg, NULL); + if (status != PJ_SUCCESS) { + showError("TCP transport creation", status); + goto on_error; + } + + // + // Create account + // + pjsua_acc_config acc_cfg; + pjsua_acc_config_default(&acc_cfg); +#if SIP_DOMAIN + acc_cfg.id = pj_str( "sip:" SIP_USERNAME "@" SIP_DOMAIN); + acc_cfg.reg_uri = pj_str((char*) ("sip:" SIP_DOMAIN)); + acc_cfg.cred_count = 1; + acc_cfg.cred_info[0].realm = pj_str((char*)"*"); + acc_cfg.cred_info[0].scheme = pj_str((char*)"digest"); + acc_cfg.cred_info[0].username = pj_str((char*)SIP_USERNAME); + acc_cfg.cred_info[0].data = pj_str((char*)SIP_PASSWORD); +#else + char sip_id[80]; + snprintf(sip_id, sizeof(sip_id), + "sip:%s@%.*s:%u", SIP_USERNAME, + (int)udp_info.local_name.host.slen, + udp_info.local_name.host.ptr, + udp_info.local_name.port); + acc_cfg.id = pj_str(sip_id); +#endif + + acc_cfg.max_video_cnt = 1; + acc_cfg.vid_cap_dev = DEFAULT_CAP_DEV; + acc_cfg.vid_rend_dev = DEFAULT_REND_DEV; + acc_cfg.vid_in_auto_show = PJ_TRUE; + acc_cfg.vid_out_auto_transmit = PJ_TRUE; + + status = pjsua_acc_add(&acc_cfg, PJ_TRUE, &accountId_); + if (status != PJ_SUCCESS) { + showError("Account creation", status); + goto on_error; + } + + localUri_->setText(acc_cfg.id.ptr); + + // + // Start pjsua! + // + showStatus("Starting stack.."); + status = pjsua_start(); + if (status != PJ_SUCCESS) { + showError("pjsua_start", status); + goto on_error; + } + + showStatus("Ready"); + + return true; + +on_error: + pjsua_destroy(); + return false; +} + +/* + * A simple registrar, invoked by default_mod_on_rx_request() + */ +static void simple_registrar(pjsip_rx_data *rdata) +{ + pjsip_tx_data *tdata; + const pjsip_expires_hdr *exp; + const pjsip_hdr *h; + unsigned cnt = 0; + pjsip_generic_string_hdr *srv; + pj_status_t status; + + status = pjsip_endpt_create_response(pjsua_get_pjsip_endpt(), + rdata, 200, NULL, &tdata); + if (status != PJ_SUCCESS) + return; + + exp = (pjsip_expires_hdr*) + pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_EXPIRES, NULL); + + h = rdata->msg_info.msg->hdr.next; + while (h != &rdata->msg_info.msg->hdr) { + if (h->type == PJSIP_H_CONTACT) { + const pjsip_contact_hdr *c = (const pjsip_contact_hdr*)h; + int e = c->expires; + + if (e < 0) { + if (exp) + e = exp->ivalue; + else + e = 3600; + } + + if (e > 0) { + pjsip_contact_hdr *nc = (pjsip_contact_hdr*) + pjsip_hdr_clone(tdata->pool, h); + nc->expires = e; + pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)nc); + ++cnt; + } + } + h = h->next; + } + + srv = pjsip_generic_string_hdr_create(tdata->pool, NULL, NULL); + srv->name = pj_str((char*)"Server"); + srv->hvalue = pj_str((char*)"pjsua simple registrar"); + pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)srv); + + pjsip_endpt_send_response2(pjsua_get_pjsip_endpt(), + rdata, tdata, NULL, NULL); +} + +/* Notification on incoming request */ +static pj_bool_t default_mod_on_rx_request(pjsip_rx_data *rdata) +{ + /* Simple registrar */ + if (pjsip_method_cmp(&rdata->msg_info.msg->line.req.method, + &pjsip_register_method) == 0) + { + simple_registrar(rdata); + return PJ_TRUE; + } + + return PJ_FALSE; +} + +/* The module instance. */ +static pjsip_module mod_default_handler = +{ + NULL, NULL, /* prev, next. */ + { (char*)"mod-default-handler", 19 }, /* Name. */ + -1, /* Id */ + PJSIP_MOD_PRIORITY_APPLICATION+99, /* Priority */ + NULL, /* load() */ + NULL, /* start() */ + NULL, /* stop() */ + NULL, /* unload() */ + &default_mod_on_rx_request, /* on_rx_request() */ + NULL, /* on_rx_response() */ + NULL, /* on_tx_request. */ + NULL, /* on_tx_response() */ + NULL, /* on_tsx_state() */ + +}; + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWin win; + win.show(); + + if (!win.initStack()) { + win.quit(); + return 1; + } + + /* Initialize our module to handle otherwise unhandled request */ + pjsip_endpt_register_module(pjsua_get_pjsip_endpt(), + &mod_default_handler); + + return app.exec(); +} + diff --git a/pjsip-apps/src/vidgui/vidgui.h b/pjsip-apps/src/vidgui/vidgui.h new file mode 100644 index 00000000..7d53e18a --- /dev/null +++ b/pjsip-apps/src/vidgui/vidgui.h @@ -0,0 +1,93 @@ +/* $Id$ */ +/* + * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef VIDGUI_H_ +#define VIDGUI_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class VidWin; + +class MainWin : public QWidget +{ + Q_OBJECT + +public: + MainWin(QWidget *parent = 0); + virtual ~MainWin(); + + static MainWin *instance(); + + bool initStack(); + void showError(const char *title, pj_status_t status); + void showStatus(const char *); + +public: + void on_reg_state(pjsua_acc_id acc_id); + void on_call_state(pjsua_call_id call_id, pjsip_event *e); + void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata); + void on_call_media_state(pjsua_call_id call_id); + +public slots: + void preview(); + void call(); + void hangup(); + void quit(); + +private: + static MainWin *theInstance_; + pjsua_acc_id accountId_; + pjsua_call_id currentCall_; + bool preview_on; + + void onNewCall(pjsua_call_id cid, bool incoming); + void onCallReleased(); + +private: + QPushButton *callButton_, + *hangupButton_, + *quitButton_, + *previewButton_; + QLineEdit *url_; + VidWin *video_; + VidWin *video_prev_; + //QStatusBar *statusBar_; + QLabel *statusBar_; + QLabel *localUri_; + + QVBoxLayout *vbox_left; + + void initLayout(); + void init_video_window(); +}; + + + +#endif /* VIDGUI_H_ */ diff --git a/pjsip-apps/src/vidgui/vidwin.cpp b/pjsip-apps/src/vidgui/vidwin.cpp new file mode 100644 index 00000000..8e207e4e --- /dev/null +++ b/pjsip-apps/src/vidgui/vidwin.cpp @@ -0,0 +1,223 @@ +#include "vidwin.h" + +#define THIS_FILE "vidwin.cpp" +#define TIMER_EMBED 1 +#define TIMER_RESIZE 2 + +void VidWin::timer_cb(pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry) +{ + 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); +} + + +VidWin::~VidWin() +{ + if (timer_entry.id) { + pjsua_cancel_timer(&timer_entry); + timer_entry.id = 0; + } +} + + +void VidWin::resizeEvent(QResizeEvent*) +{ + /* 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); +} + +/* Platform specific code */ + +#if defined(PJ_WIN32) && !defined(PJ_WIN32_WINCE) + +#include + +void VidWin::embed() +{ + /* Embed hwnd to widget */ + pj_assert(hwnd.type == PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS); + HWND h = (HWND)hwnd.info.win.hwnd; + HWND new_parent = (HWND)winId(); + + //old_parent_hwnd.type = PJMEDIA_VID_DEV_HWND_TYPE_WINDOWS; + //old_parent_hwnd.info.win.hwnd = GetParent(h); + + 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)); +} + +void VidWin::resize() +{ + /* Update position and size */ + HWND h = (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())); +} + +#elif defined(PJ_DARWINOS) + +#import + +void VidWin::embed() +{ + /* 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]; + + //[w setStyleMask:NSBorderlessWindowMask]; + + //[w setParentWindow:parent]; + [parent addChildWindow:w ordered:NSWindowAbove]; + PJ_LOG(3, (THIS_FILE, "%p parent handle = %p", w, parent)); +} + + +void VidWin::resize() +{ + /* 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())); +} + +#elif defined(PJ_LINUX) + +#include +//#include + +void VidWin::embed() +{ + /* 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(); + Window w = (Window)hwnd.info.x11.window; + Window parent = (Window)this->winId(); + + 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::resize() +{ + /* Update position and size */ + Display *d = (Display*)hwnd.info.x11.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); +} + +#endif + diff --git a/pjsip-apps/src/vidgui/vidwin.h b/pjsip-apps/src/vidgui/vidwin.h new file mode 100644 index 00000000..629a960e --- /dev/null +++ b/pjsip-apps/src/vidgui/vidwin.h @@ -0,0 +1,33 @@ +#ifndef VIDWIN_H +#define VIDWIN_H + +#include +#include + +class VidWin : public QWidget +{ + Q_OBJECT + +public: + // hwnd Handle of the video rendering window. + VidWin(pjmedia_vid_dev_hwnd *hwnd = NULL, + QWidget* parent = 0, + Qt::WindowFlags f = 0); + virtual ~VidWin(); + +protected: + void resizeEvent(QResizeEvent *e); + +private: + pjmedia_vid_dev_hwnd hwnd; + //pjmedia_vid_dev_hwnd old_parent_hwnd; + pj_timer_entry timer_entry; + + static void timer_cb(pj_timer_heap_t *timer_heap, + struct pj_timer_entry *entry); + + void embed(); + void resize(); +}; + +#endif -- cgit v1.2.3