author | llornkcor <llornkcor> | 2006-07-09 18:56:40 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2006-07-09 18:56:40 (UTC) |
commit | 36dece4760b1ac1799929221b49eb3bee98c2367 (patch) (side-by-side diff) | |
tree | a45f66d2d90bd9fbbff8e8903cd1cb9323c39f6e /noncore | |
parent | 604065c6e662cb3894acf03abadafacc3ab52913 (diff) | |
download | opie-36dece4760b1ac1799929221b49eb3bee98c2367.zip opie-36dece4760b1ac1799929221b49eb3bee98c2367.tar.gz opie-36dece4760b1ac1799929221b49eb3bee98c2367.tar.bz2 |
initial commit to add video4linux camera app from qtopia 2, needs more work
-rw-r--r-- | noncore/multimedia/camera2/camera2.pro | 27 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerabase.cpp | 93 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerabase.h | 47 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerabase.ui | 209 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerasettings.cpp | 166 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerasettings.h | 59 | ||||
-rw-r--r-- | noncore/multimedia/camera2/camerasettings.ui | 433 | ||||
-rw-r--r-- | noncore/multimedia/camera2/config.in | 7 | ||||
-rw-r--r-- | noncore/multimedia/camera2/image.cpp | 239 | ||||
-rw-r--r-- | noncore/multimedia/camera2/image.h | 53 | ||||
-rw-r--r-- | noncore/multimedia/camera2/main.cpp | 44 | ||||
-rw-r--r-- | noncore/multimedia/camera2/mainwindow.cpp | 763 | ||||
-rw-r--r-- | noncore/multimedia/camera2/mainwindow.h | 132 | ||||
-rw-r--r-- | noncore/multimedia/camera2/opie-camera2.control | 10 | ||||
-rw-r--r-- | noncore/multimedia/camera2/thumbbutton.h | 50 | ||||
-rw-r--r-- | noncore/multimedia/camera2/videocaptureview.cpp | 599 | ||||
-rw-r--r-- | noncore/multimedia/camera2/videocaptureview.h | 82 |
17 files changed, 3013 insertions, 0 deletions
diff --git a/noncore/multimedia/camera2/camera2.pro b/noncore/multimedia/camera2/camera2.pro new file mode 100644 index 0000000..b6e2826 --- a/dev/null +++ b/noncore/multimedia/camera2/camera2.pro @@ -0,0 +1,27 @@ +DESTDIR = $(OPIEDIR)/bin +TEMPLATE = app +CONFIG += qte warn_on quick_app +INTERFACES=camerabase.ui camerasettings.ui +HEADERS = mainwindow.h \ + image.h \ + thumbbutton.h \ + videocaptureview.h +SOURCES = mainwindow.cpp\ + image.cpp \ + videocaptureview.cpp \ + main.cpp + +TARGET = camera2 +DEFINES += HAVE_VIDEO4LINUX + +LIBS += -lopiecore2 -lopieui2 +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +contains(CONFIG,quick-app) { + DESTDIR = $(OPIEDIR)/bin + DEFINES += NOQUICKLAUNCH +} + + +include( $(OPIEDIR)/include.pro ) + diff --git a/noncore/multimedia/camera2/camerabase.cpp b/noncore/multimedia/camera2/camerabase.cpp new file mode 100644 index 0000000..cbb1ba9 --- a/dev/null +++ b/noncore/multimedia/camera2/camerabase.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'camerabase.ui' +** +** Created: Mon Jul 10 04:21:25 2006 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "camerabase.h" + +#include <qframe.h> +#include <qpushbutton.h> +#include "thumbbutton.h" +#include "videocaptureview.h" +#include <qlayout.h> +#include <qvariant.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a CameraBase which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + */ +CameraBase::CameraBase( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "camera" ); + resize( 311, 381 ); + setCaption( tr( "Camera" ) ); + cameraLayout = new QGridLayout( this ); + cameraLayout->setSpacing( 0 ); + cameraLayout->setMargin( 0 ); + + Frame3 = new QFrame( this, "Frame3" ); + Frame3->setFrameShape( QFrame::Panel ); + Frame3->setFrameShadow( QFrame::Sunken ); + Frame3->setLineWidth( 4 ); + Frame3->setMargin( 4 ); + Frame3->setMidLineWidth( 3 ); + Frame3Layout = new QVBoxLayout( Frame3 ); + Frame3Layout->setSpacing( 6 ); + Frame3Layout->setMargin( 4 ); + + videocaptureview = new VideoCaptureView( Frame3, "videocaptureview" ); + videocaptureview->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, videocaptureview->sizePolicy().hasHeightForWidth() ) ); + Frame3Layout->addWidget( videocaptureview ); + + cameraLayout->addMultiCellWidget( Frame3, 0, 0, 0, 1 ); + + photo = new QPushButton( this, "photo" ); + photo->setText( tr( "Photo" ) ); + + cameraLayout->addWidget( photo, 1, 0 ); + + video = new QPushButton( this, "video" ); + video->setText( tr( "Video" ) ); + + cameraLayout->addWidget( video, 1, 1 ); + + thumbs = new QFrame( this, "thumbs" ); + thumbs->setFrameShape( QFrame::NoFrame ); + thumbs->setFrameShadow( QFrame::Plain ); + thumbsLayout = new QHBoxLayout( thumbs ); + thumbsLayout->setSpacing( 0 ); + thumbsLayout->setMargin( 0 ); + + thumb1 = new ThumbButton( thumbs, "thumb1" ); + thumbsLayout->addWidget( thumb1 ); + + thumb2 = new ThumbButton( thumbs, "thumb2" ); + thumbsLayout->addWidget( thumb2 ); + + thumb3 = new ThumbButton( thumbs, "thumb3" ); + thumbsLayout->addWidget( thumb3 ); + + thumb4 = new ThumbButton( thumbs, "thumb4" ); + thumbsLayout->addWidget( thumb4 ); + + thumb5 = new ThumbButton( thumbs, "thumb5" ); + thumbsLayout->addWidget( thumb5 ); + + cameraLayout->addMultiCellWidget( thumbs, 2, 2, 0, 1 ); +} + +/* + * Destroys the object and frees any allocated resources + */ +CameraBase::~CameraBase() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/noncore/multimedia/camera2/camerabase.h b/noncore/multimedia/camera2/camerabase.h new file mode 100644 index 0000000..77ab4f0 --- a/dev/null +++ b/noncore/multimedia/camera2/camerabase.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'camerabase.ui' +** +** Created: Mon Jul 10 04:21:22 2006 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef CAMERA_H +#define CAMERA_H + +#include <qvariant.h> +#include <qwidget.h> +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QFrame; +class QPushButton; +class ThumbButton; +class VideoCaptureView; + +class CameraBase : public QWidget +{ + Q_OBJECT + +public: + CameraBase( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~CameraBase(); + + QFrame* Frame3; + VideoCaptureView* videocaptureview; + QPushButton* photo; + QPushButton* video; + QFrame* thumbs; + ThumbButton* thumb1; + ThumbButton* thumb2; + ThumbButton* thumb3; + ThumbButton* thumb4; + ThumbButton* thumb5; + +protected: + QGridLayout* cameraLayout; + QVBoxLayout* Frame3Layout; + QHBoxLayout* thumbsLayout; +}; + +#endif // CAMERA_H diff --git a/noncore/multimedia/camera2/camerabase.ui b/noncore/multimedia/camera2/camerabase.ui new file mode 100644 index 0000000..e102f79 --- a/dev/null +++ b/noncore/multimedia/camera2/camerabase.ui @@ -0,0 +1,209 @@ +<!DOCTYPE UI><UI> +<class>CameraBase</class> +<widget> + <class>QWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>camera</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>311</width> + <height>381</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Camera</string> + </property> + <grid> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>0</number> + </property> + <widget row="0" column="0" rowspan="1" colspan="2" > + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>Frame3</cstring> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>Panel</enum> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Sunken</enum> + </property> + <property stdset="1"> + <name>lineWidth</name> + <number>4</number> + </property> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>midLineWidth</name> + <number>3</number> + </property> + <property> + <name>layoutMargin</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>VideoCaptureView</class> + <property stdset="1"> + <name>name</name> + <cstring>videocaptureview</cstring> + </property> + <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + </sizepolicy> + </property> + </widget> + </vbox> + </widget> + <widget row="1" column="0" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>photo</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Photo</string> + </property> + </widget> + <widget row="1" column="1" > + <class>QPushButton</class> + <property stdset="1"> + <name>name</name> + <cstring>video</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Video</string> + </property> + </widget> + <widget row="2" column="0" rowspan="1" colspan="2" > + <class>QFrame</class> + <property stdset="1"> + <name>name</name> + <cstring>thumbs</cstring> + </property> + <property stdset="1"> + <name>frameShape</name> + <enum>NoFrame</enum> + </property> + <property stdset="1"> + <name>frameShadow</name> + <enum>Plain</enum> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>0</number> + </property> + <widget> + <class>ThumbButton</class> + <property stdset="1"> + <name>name</name> + <cstring>thumb1</cstring> + </property> + </widget> + <widget> + <class>ThumbButton</class> + <property stdset="1"> + <name>name</name> + <cstring>thumb2</cstring> + </property> + </widget> + <widget> + <class>ThumbButton</class> + <property stdset="1"> + <name>name</name> + <cstring>thumb3</cstring> + </property> + </widget> + <widget> + <class>ThumbButton</class> + <property stdset="1"> + <name>name</name> + <cstring>thumb4</cstring> + </property> + </widget> + <widget> + <class>ThumbButton</class> + <property stdset="1"> + <name>name</name> + <cstring>thumb5</cstring> + </property> + </widget> + </hbox> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>VideoCaptureView</class> + <header location="local">videocaptureview.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>7</hordata> + <verdata>7</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> + <customwidget> + <class>ThumbButton</class> + <header location="local">thumbbutton.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image1</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> + <image> + <name>image1</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1ddec44f503c0ae2a154410f53d0ed20e2bf6bdb656dd6861dd23d9a66591b0587fd1654235ebded6f0edcd53e419d87ae7b1f4f9b8f906d0bfe012317426a70b07bdc2f3ec77f8ed6b89559061a0343d06a124cc105596482585094bc0ae599b04646c9018926491b2205e140c485cace25755c175d0a967b622ff900b8cc9c7d29af594ea722d589167f813aa852ba07d94b9dce296e883fe7bb163f23896753</data> + </image> +</images> +</UI> diff --git a/noncore/multimedia/camera2/camerasettings.cpp b/noncore/multimedia/camera2/camerasettings.cpp new file mode 100644 index 0000000..d284128 --- a/dev/null +++ b/noncore/multimedia/camera2/camerasettings.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'camerasettings.ui' +** +** Created: Mon Jul 10 04:21:25 2006 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "camerasettings.h" + +#include <qcombobox.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtopia/locationcombo.h> +#include <qlayout.h> +#include <qvariant.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a CameraSettings which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +CameraSettings::CameraSettings( QWidget* parent, const char* name, bool modal, WFlags fl ) + : QDialog( parent, name, modal, fl ) +{ + if ( !name ) + setName( "CameraSettings" ); + resize( 324, 465 ); + setCaption( tr( "Settings" ) ); + CameraSettingsLayout = new QVBoxLayout( this ); + CameraSettingsLayout->setSpacing( 6 ); + CameraSettingsLayout->setMargin( 11 ); + + location = new LocationCombo( this, "location" ); + CameraSettingsLayout->addWidget( location ); + + photo = new QGroupBox( this, "photo" ); + photo->setTitle( tr( "Photo" ) ); + photo->setColumnLayout(0, Qt::Vertical ); + photo->layout()->setSpacing( 0 ); + photo->layout()->setMargin( 0 ); + photoLayout = new QVBoxLayout( photo->layout() ); + photoLayout->setAlignment( Qt::AlignTop ); + photoLayout->setSpacing( 2 ); + photoLayout->setMargin( 4 ); + + Layout1 = new QHBoxLayout; + Layout1->setSpacing( 6 ); + Layout1->setMargin( 0 ); + + TextLabel1 = new QLabel( photo, "TextLabel1" ); + TextLabel1->setText( tr( "Size" ) ); + Layout1->addWidget( TextLabel1 ); + + photo_size = new QComboBox( FALSE, photo, "photo_size" ); + photo_size->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, photo_size->sizePolicy().hasHeightForWidth() ) ); + Layout1->addWidget( photo_size ); + photoLayout->addLayout( Layout1 ); + + Layout2 = new QHBoxLayout; + Layout2->setSpacing( 6 ); + Layout2->setMargin( 0 ); + + TextLabel2 = new QLabel( photo, "TextLabel2" ); + TextLabel2->setText( tr( "Quality" ) ); + Layout2->addWidget( TextLabel2 ); + + photo_quality = new QSlider( photo, "photo_quality" ); + photo_quality->setMinValue( 0 ); + photo_quality->setMaxValue( 100 ); + photo_quality->setValue( 75 ); + photo_quality->setOrientation( QSlider::Horizontal ); + Layout2->addWidget( photo_quality ); + + photo_quality_n = new QLabel( photo, "photo_quality_n" ); + photo_quality_n->setText( tr( "75" ) ); + Layout2->addWidget( photo_quality_n ); + photoLayout->addLayout( Layout2 ); + CameraSettingsLayout->addWidget( photo ); + + video = new QGroupBox( this, "video" ); + video->setTitle( tr( "Video" ) ); + video->setColumnLayout(0, Qt::Vertical ); + video->layout()->setSpacing( 0 ); + video->layout()->setMargin( 0 ); + videoLayout = new QVBoxLayout( video->layout() ); + videoLayout->setAlignment( Qt::AlignTop ); + videoLayout->setSpacing( 2 ); + videoLayout->setMargin( 4 ); + + Layout1_2 = new QHBoxLayout; + Layout1_2->setSpacing( 6 ); + Layout1_2->setMargin( 0 ); + + TextLabel1_2 = new QLabel( video, "TextLabel1_2" ); + TextLabel1_2->setText( tr( "Size" ) ); + Layout1_2->addWidget( TextLabel1_2 ); + + video_size = new QComboBox( FALSE, video, "video_size" ); + video_size->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)0, video_size->sizePolicy().hasHeightForWidth() ) ); + Layout1_2->addWidget( video_size ); + videoLayout->addLayout( Layout1_2 ); + + Layout2_2 = new QHBoxLayout; + Layout2_2->setSpacing( 6 ); + Layout2_2->setMargin( 0 ); + + TextLabel2_2 = new QLabel( video, "TextLabel2_2" ); + TextLabel2_2->setText( tr( "Quality" ) ); + Layout2_2->addWidget( TextLabel2_2 ); + + video_quality = new QSlider( video, "video_quality" ); + video_quality->setMinValue( 0 ); + video_quality->setMaxValue( 100 ); + video_quality->setValue( 75 ); + video_quality->setOrientation( QSlider::Horizontal ); + Layout2_2->addWidget( video_quality ); + + video_quality_n = new QLabel( video, "video_quality_n" ); + video_quality_n->setText( tr( "75" ) ); + Layout2_2->addWidget( video_quality_n ); + videoLayout->addLayout( Layout2_2 ); + + Layout6 = new QHBoxLayout; + Layout6->setSpacing( 6 ); + Layout6->setMargin( 0 ); + + TextLabel4 = new QLabel( video, "TextLabel4" ); + TextLabel4->setText( tr( "Frame rate" ) ); + Layout6->addWidget( TextLabel4 ); + + video_framerate = new QSlider( video, "video_framerate" ); + video_framerate->setMinValue( 1 ); + video_framerate->setMaxValue( 60 ); + video_framerate->setValue( 5 ); + video_framerate->setOrientation( QSlider::Horizontal ); + Layout6->addWidget( video_framerate ); + + TextLabel6 = new QLabel( video, "TextLabel6" ); + TextLabel6->setText( tr( "5" ) ); + Layout6->addWidget( TextLabel6 ); + videoLayout->addLayout( Layout6 ); + CameraSettingsLayout->addWidget( video ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + CameraSettingsLayout->addItem( spacer ); + + // signals and slots connections + connect( photo_quality, SIGNAL( valueChanged(int) ), photo_quality_n, SLOT( setNum(int) ) ); + connect( video_quality, SIGNAL( valueChanged(int) ), video_quality_n, SLOT( setNum(int) ) ); + connect( video_framerate, SIGNAL( valueChanged(int) ), TextLabel6, SLOT( setNum(int) ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +CameraSettings::~CameraSettings() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/noncore/multimedia/camera2/camerasettings.h b/noncore/multimedia/camera2/camerasettings.h new file mode 100644 index 0000000..dcc48a0 --- a/dev/null +++ b/noncore/multimedia/camera2/camerasettings.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'camerasettings.ui' +** +** Created: Mon Jul 10 04:21:22 2006 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef CAMERASETTINGS_H +#define CAMERASETTINGS_H + +#include <qvariant.h> +#include <qdialog.h> +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class LocationCombo; +class QComboBox; +class QGroupBox; +class QLabel; +class QSlider; + +class CameraSettings : public QDialog +{ + Q_OBJECT + +public: + CameraSettings( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~CameraSettings(); + + LocationCombo* location; + QGroupBox* photo; + QLabel* TextLabel1; + QComboBox* photo_size; + QLabel* TextLabel2; + QSlider* photo_quality; + QLabel* photo_quality_n; + QGroupBox* video; + QLabel* TextLabel1_2; + QComboBox* video_size; + QLabel* TextLabel2_2; + QSlider* video_quality; + QLabel* video_quality_n; + QLabel* TextLabel4; + QSlider* video_framerate; + QLabel* TextLabel6; + +protected: + QVBoxLayout* CameraSettingsLayout; + QVBoxLayout* photoLayout; + QHBoxLayout* Layout1; + QHBoxLayout* Layout2; + QVBoxLayout* videoLayout; + QHBoxLayout* Layout1_2; + QHBoxLayout* Layout2_2; + QHBoxLayout* Layout6; +}; + +#endif // CAMERASETTINGS_H diff --git a/noncore/multimedia/camera2/camerasettings.ui b/noncore/multimedia/camera2/camerasettings.ui new file mode 100644 index 0000000..276694b --- a/dev/null +++ b/noncore/multimedia/camera2/camerasettings.ui @@ -0,0 +1,433 @@ +<!DOCTYPE UI><UI> +<class>CameraSettings</class> +<widget> + <class>QDialog</class> + <property stdset="1"> + <name>name</name> + <cstring>CameraSettings</cstring> + </property> + <property stdset="1"> + <name>geometry</name> + <rect> + <x>0</x> + <y>0</y> + <width>324</width> + <height>465</height> + </rect> + </property> + <property stdset="1"> + <name>caption</name> + <string>Settings</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>11</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>LocationCombo</class> + <property stdset="1"> + <name>name</name> + <cstring>location</cstring> + </property> + </widget> + <widget> + <class>QGroupBox</class> + <property stdset="1"> + <name>name</name> + <cstring>photo</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Photo</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>2</number> + </property> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout1</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Size</string> + </property> + </widget> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>photo_size</cstring> + </property> + <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout2</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Quality</string> + </property> + </widget> + <widget> + <class>QSlider</class> + <property stdset="1"> + <name>name</name> + <cstring>photo_quality</cstring> + </property> + <property stdset="1"> + <name>minValue</name> + <number>0</number> + </property> + <property stdset="1"> + <name>maxValue</name> + <number>100</number> + </property> + <property stdset="1"> + <name>value</name> + <number>75</number> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>photo_quality_n</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>75</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget> + <class>QGroupBox</class> + <property stdset="1"> + <name>name</name> + <cstring>video</cstring> + </property> + <property stdset="1"> + <name>title</name> + <string>Video</string> + </property> + <property> + <name>layoutMargin</name> + </property> + <property> + <name>layoutSpacing</name> + </property> + <vbox> + <property stdset="1"> + <name>margin</name> + <number>4</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>2</number> + </property> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout1_2</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel1_2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Size</string> + </property> + </widget> + <widget> + <class>QComboBox</class> + <property stdset="1"> + <name>name</name> + <cstring>video_size</cstring> + </property> + <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout2_2</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel2_2</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Quality</string> + </property> + </widget> + <widget> + <class>QSlider</class> + <property stdset="1"> + <name>name</name> + <cstring>video_quality</cstring> + </property> + <property stdset="1"> + <name>minValue</name> + <number>0</number> + </property> + <property stdset="1"> + <name>maxValue</name> + <number>100</number> + </property> + <property stdset="1"> + <name>value</name> + <number>75</number> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>video_quality_n</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>75</string> + </property> + </widget> + </hbox> + </widget> + <widget> + <class>QLayoutWidget</class> + <property stdset="1"> + <name>name</name> + <cstring>Layout6</cstring> + </property> + <hbox> + <property stdset="1"> + <name>margin</name> + <number>0</number> + </property> + <property stdset="1"> + <name>spacing</name> + <number>6</number> + </property> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel4</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>Frame rate</string> + </property> + </widget> + <widget> + <class>QSlider</class> + <property stdset="1"> + <name>name</name> + <cstring>video_framerate</cstring> + </property> + <property stdset="1"> + <name>minValue</name> + <number>1</number> + </property> + <property stdset="1"> + <name>maxValue</name> + <number>60</number> + </property> + <property stdset="1"> + <name>value</name> + <number>5</number> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Horizontal</enum> + </property> + </widget> + <widget> + <class>QLabel</class> + <property stdset="1"> + <name>name</name> + <cstring>TextLabel6</cstring> + </property> + <property stdset="1"> + <name>text</name> + <string>5</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer> + <property> + <name>name</name> + <cstring>Spacer1</cstring> + </property> + <property stdset="1"> + <name>orientation</name> + <enum>Vertical</enum> + </property> + <property stdset="1"> + <name>sizeType</name> + <enum>Expanding</enum> + </property> + <property> + <name>sizeHint</name> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>LocationCombo</class> + <header location="global">qtopia/locationcombo.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image> + <name>image0</name> + <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758</data> + </image> +</images> +<connections> + <connection> + <sender>photo_quality</sender> + <signal>valueChanged(int)</signal> + <receiver>photo_quality_n</receiver> + <slot>setNum(int)</slot> + </connection> + <connection> + <sender>video_quality</sender> + <signal>valueChanged(int)</signal> + <receiver>video_quality_n</receiver> + <slot>setNum(int)</slot> + </connection> + <connection> + <sender>video_framerate</sender> + <signal>valueChanged(int)</signal> + <receiver>TextLabel6</receiver> + <slot>setNum(int)</slot> + </connection> +</connections> +</UI> diff --git a/noncore/multimedia/camera2/config.in b/noncore/multimedia/camera2/config.in new file mode 100644 index 0000000..8838008 --- a/dev/null +++ b/noncore/multimedia/camera2/config.in @@ -0,0 +1,7 @@ + config CAMERA2 + boolean "opie-camera2 (camera app to use with Video4Linux)" + default "n" + depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2UI + comment "opie-camera needs a libqpe, libopie2core & libopie2ui" + depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE && LIBOPIE2UI ) + diff --git a/noncore/multimedia/camera2/image.cpp b/noncore/multimedia/camera2/image.cpp new file mode 100644 index 0000000..39b6d8b --- a/dev/null +++ b/noncore/multimedia/camera2/image.cpp @@ -0,0 +1,239 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "image.h" + +#include <qfileinfo.h> +#include <qimage.h> +#include <qstring.h> + +/*! + Returns an image created by loading the \a filename, + and scalining it, preserving aspect ratio, to fit in + \a width by \a height pixels. + + First availability: Qtopia 2.0 +*/ +QImage Image::loadScaled(const QString & filename, const int width, const int height, + ScaleMode mode) +{ + QImageIO iio; + QString param; + int w = width; + int h = height; + + if (width == 0 || height == 0) + return QImage(); + + iio.setFileName(filename); + + // + // Try and load and scale the image in one hit. + // + param.sprintf("GetHeaderInformation"); + iio.setParameters(param); + iio.read(); + + // + // If we don't have bits(), read() understands parameters, + // and we can setup for fast reading. Otherwise, take the + // performance hit and do things slowly. + // + if (!iio.image().bits()) { + if ((iio.image().width() < w) && (iio.image().height() < h)) { + param.sprintf("%s", "Fast"); // No Tr + } + else { + int shrink_factor = 1; + QString smode; + switch (mode) { + case ScaleMin: + smode = "ScaleMin"; + shrink_factor = QMAX(iio.image().width() / w, iio.image().height() / h); + break; + case ScaleMax: + smode = "ScaleMax"; + shrink_factor = QMIN(iio.image().width() / w, iio.image().height() / h); + break; + case ScaleFree: + smode = "ScaleFree"; + shrink_factor = QMIN(iio.image().width() / w, iio.image().height() / h); + break; + } + param.sprintf("Scale( %i, %i, %s )%s, Shrink( %i )", // No tr + w, h, smode.latin1(), ", Fast", shrink_factor); // No tr + } + + iio.setParameters(param); + iio.read(); + return iio.image(); + } + + if ((iio.image().width() > w) || (iio.image().height() > h)) { + QSize s = aspectScaleSize(iio.image().width(), iio.image().height(), w, h, mode); + return iio.image().smoothScale(s.width(), s.height()); + } + + return iio.image(); +} + +// +// Returns new size of image, scaled to target_width and target_height, +// whilst preserving aspect ratio. Useful when it's not possible to +// scale an image prior to using it (eg. using RichText). Should be in +// global image utils. +// +// NOTE +// - expensive for images whose drivers do not allow us to retrieve +// parameters without reading the entire image. Currently (20030930) +// only the jpeg driver allows parameter reading. +// +QSize Image::loadScaledImageSize(const QString & filename, int target_width, int target_height, + int maxscale, ScaleMode mode) +{ + QImageIO iio; + iio.setFileName(filename); + iio.setParameters("GetHeaderInformation"); + iio.read(); + + int w = iio.image().width(); + int h = iio.image().height(); + + // + // Scaling up small pictures can be very ugly. + // Leave them alone if they are too small. + // + if (maxscale && w * maxscale < target_width && h * maxscale < target_height) + return QSize(w * maxscale, h * maxscale); + + return aspectScaleSize(w, h, target_width, target_height, mode); +} + +// Load an image to be used as a portrait. Force its height to height, +// scale width to new height, and crop the width if it's still > width +// XXX : Should be using integer math +QImage Image::loadPortrait(const QString & filename, const int width, const int height) +{ + QImageIO iio; + QString param; + int w = width; + int h = height; + + if (width == 0 || height == 0) + return QImage(); + + iio.setFileName(filename); + + // + // Try and load and scale the image in one hit. + // + param.sprintf("GetHeaderInformation"); + iio.setParameters(param); + iio.read(); + + // + // If we don't have bits(), read() understands parameters, + // and we can setup for fast reading. Otherwise, take the + // performance hit and do things slowly. + // + if (!iio.image().bits()) { + + w = (int) ((double) iio.image().width() / (double) (iio.image().height()) * + (double) height); + param.sprintf("Scale( %i, %i, ScaleFree )%s", // No tr + w, h, ", Fast"); // No tr + + iio.setParameters(param); + iio.read(); + + if (w > width) { + int x = (int) ((double) (w - width) / 2); + QRect r(x, 0, width, height); + return iio.image().copy(r); + } + else + return iio.image(); + } + else + //scale width to the new height + return sizeToPortrait(iio.image(), width, height); +} + +QImage Image::sizeToPortrait(const QImage & image, const int width, const int height) +{ + int w = (image.width() * height) / image.height(); + if (w > width) { + int x = (w - width) / 2; + QRect r(x, 0, width, height); + return image.smoothScale(w, height).copy(r); + } + else + return image.smoothScale(width, height); +} + +// +// Return (w x h) scaled to (target_width x target_height) with aspect +// ratio preserved. +// +QSize + Image::aspectScaleSize(const int w, const int h, const int target_width, + const int target_height, ScaleMode mode) +{ + QSize s; + if (mode == ScaleFree) { + s = QSize(target_width, target_height); + } + else { + bool useHeight = TRUE; + int rw = target_height * w / h; + + if (mode == ScaleMin) { + useHeight = (rw <= target_width); + } + else { // mode == ScaleMax + useHeight = (rw >= target_width); + } + + if (useHeight) { + s = QSize(rw, target_height); + } + else { + s = QSize(target_width, target_width * h / w); + } + } + + return s; +} + diff --git a/noncore/multimedia/camera2/image.h b/noncore/multimedia/camera2/image.h new file mode 100644 index 0000000..36394ff --- a/dev/null +++ b/noncore/multimedia/camera2/image.h @@ -0,0 +1,53 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#ifndef IMAGE_H +#define IMAGE_H + +#include <qimage.h> +#include <qtopia/qpeglobal.h> + +class Image { +public: + // namespace + enum ScaleMode { ScaleFree, ScaleMin, ScaleMax }; + static QImage loadScaled(const QString &filename, const int width, const int height, ScaleMode mode=ScaleMin); + static QSize loadScaledImageSize(const QString &filename, int target_width, int target_height, int maxscale=1, ScaleMode mode=ScaleMin); + static QImage loadPortrait(const QString &filename, const int width, const int height); + static QImage sizeToPortrait(const QImage &image, const int width, const int height); + static QSize aspectScaleSize(const int w, const int h, const int target_width, const int target_height, ScaleMode mode=ScaleMin); +}; + +#endif // IMAGE_H diff --git a/noncore/multimedia/camera2/main.cpp b/noncore/multimedia/camera2/main.cpp new file mode 100644 index 0000000..00e21de --- a/dev/null +++ b/noncore/multimedia/camera2/main.cpp @@ -0,0 +1,44 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "mainwindow.h" +#include <opie2/oapplication.h> +#include <opie2/oapplicationfactory.h> + +using namespace Opie::Core; +OPIE_EXPORT_APP(OApplicationFactory < CameraMainWindow >) +// QTOPIA_ADD_APPLICATION("camera",CameraMainWindow) +// QTOPIA_MAIN + diff --git a/noncore/multimedia/camera2/mainwindow.cpp b/noncore/multimedia/camera2/mainwindow.cpp new file mode 100644 index 0000000..45f8cdf --- a/dev/null +++ b/noncore/multimedia/camera2/mainwindow.cpp @@ -0,0 +1,763 @@ +/********************************************************************** + ** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. + ** + ** This file is part of the Qtopia Environment. + ** + ** 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. + ** + ** A copy of the GNU GPL license version 2 is included in this package as + ** LICENSE.GPL. + ** + ** 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. + ** + ** In addition, as a special exception Trolltech gives permission to link + ** the code of this program with Qtopia applications copyrighted, developed + ** and distributed by Trolltech under the terms of the Qtopia Personal Use + ** License Agreement. You must comply with the GNU General Public License + ** in all respects for all of the code used other than the applications + ** licensed under the Qtopia Personal Use License Agreement. If you modify + ** this file, you may extend this exception to your version of the file, + ** but you are not obligated to do so. If you do not wish to do so, delete + ** this exception statement from your version. + ** + ** See http://www.trolltech.com/gpl/ for GPL licensing information. + ** + ** Contact info@trolltech.com if any conditions of this licensing are + ** not clear to you. + ** + **********************************************************************/ + +#define QTOPIA_INTERNAL_FILEOPERATIONS +#include "mainwindow.h" +#include "videocaptureview.h" +#include "camerasettings.h" +#include "thumbbutton.h" + +#include "image.h" + +/* OPIE */ +#include <opie2/odebug.h> +#include <opie2/oresource.h> +using namespace Opie::Core; + +#include <qpe/config.h> +#include <qpe/qpeapplication.h> +#include <qpe/locationcombo.h> +//#include <qtopia/contextmenu.h> +#include <qpe/qcopenvelope_qws.h> +#include <qpe/resource.h> +//#include <qtopia/services.h> +#include <qpe/categories.h> +#include <qpe/qpetoolbar.h> +#include <qpe/global.h> + +#include <qaction.h> +#include <qlabel.h> +#include <qtoolbutton.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qsignalmapper.h> +#include <qdir.h> +#include <qimage.h> +#include <qslider.h> +#include <qtimer.h> +#include <qmessagebox.h> + +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> + +static const int thmarg = 2; +static const bool video_supported = FALSE; + +CameraMainWindow::CameraMainWindow(QWidget * parent, const char *name, WFlags f) +:QMainWindow(parent, name, f) +{ + setCaption(tr("Camera")); + + picfile = Global::tempDir() + "image.jpg"; + camera = new CameraBase(this); + setCentralWidget(camera); + + connect(qApp, SIGNAL(appMessage(const QCString &, const QByteArray &)), + this, SLOT(appMessage(const QCString &, const QByteArray &))); + connect(qApp, SIGNAL(linkChanged(const QString &)), this, SLOT(linkChanged(const QString &))); + + Categories cats; + cats.load(categoryFileName()); + camcat = cats.id("Document View", "_Camera"); // No tr + if (!camcat) { + camcat = cats.addCategory("Document View", "_Camera"); // No tr + cats.save(categoryFileName()); + } + + camera->photo->setFocus(); + + connect(camera->photo, SIGNAL(clicked()), this, SLOT(takePhoto())); + connect(camera->video, SIGNAL(clicked()), this, SLOT(toggleVideo())); + + refocusTimer = new QTimer(this); + connect(refocusTimer, SIGNAL(timeout()), this, SLOT(takePhotoNow())); + + thumb[0] = camera->thumb1; + thumb[1] = camera->thumb2; + thumb[2] = camera->thumb3; + thumb[3] = camera->thumb4; + thumb[4] = camera->thumb5; + cur_thumb = -1; + + QSignalMapper *sm = new QSignalMapper(this); + for (int i = 0; i < nthumb; i++) { + sm->setMapping(thumb[i], i); + connect(thumb[i], SIGNAL(clicked()), sm, SLOT(map())); + thumb[i]->installEventFilter(this); + } + connect(sm, SIGNAL(mapped(int)), this, SLOT(thumbClicked(int))); + +#warning fixme +// AppLnk picture_viewer = Service::appLnk("PhotoEdit"); +// AppLnk video_viewer = Service::appLnk("Open/video/mpeg"); + + a_pview = new QAction(tr("%1...", "app name").arg("" /*picture_viewer.name() */ ), + Resource::loadPixmap(NULL /*picture_viewer.icon() */ ), QString::null, 0, + this, 0); + connect(a_pview, SIGNAL(activated()), this, SLOT(viewPictures())); + a_vview = new QAction(tr("%1...", "app name").arg("" /*video_viewer.name() */ ), + Resource::loadIconSet(NULL /*video_viewer.icon() */ ), QString::null, 0, + this, 0); + connect(a_vview, SIGNAL(activated()), this, SLOT(viewVideos())); + + a_settings = + new QAction(tr("Settings..."), Opie::Core::OResource::loadPixmap("camera2/settings", Opie::Core::OResource::SmallIcon), + QString::null, 0, this, 0); + connect(a_settings, SIGNAL(activated()), this, SLOT(doSettings())); + + a_th_edit = new QAction(tr("Edit"), Opie::Core::OResource::loadPixmap("edit", Opie::Core::OResource::SmallIcon), + QString::null, 0, this, 0); + connect(a_th_edit, SIGNAL(activated()), this, SLOT(editThumb())); + a_th_del = new QAction(tr("Delete"), Opie::Core::OResource::loadPixmap("trash", Opie::Core::OResource::SmallIcon), + QString::null, 0, this, 0); + connect(a_th_del, SIGNAL(activated()), this, SLOT(delThumb())); + a_th_add = + new QAction(tr("Move to Contact..."), Opie::Core::OResource::loadPixmap("addressbook/generic-contact", Opie::Core::OResource::SmallIcon), + QString::null, 0, this, 0); + connect(a_th_add, SIGNAL(activated()), this, SLOT(moveToContact())); + a_send = + new QAction(tr("Beam to Contact..."), Opie::Core::OResource::loadPixmap("beam", Opie::Core::OResource::SmallIcon), + QString::null, 0, this, 0); + connect(a_send, SIGNAL(activated()), this, SLOT(sendFile())); + + +#ifndef QTOPIA_PHONE + // Create Toolbars + QPEToolBar *bar = new QPEToolBar(this); + bar->setHorizontalStretchable(TRUE); + setToolBarsMovable(FALSE); + + a_pview->addTo(bar); + if (video_supported) + a_vview->addTo(bar); + a_th_edit->addTo(bar); + a_th_del->addTo(bar); + a_th_add->addTo(bar); + a_send->addTo(bar); + a_settings->addTo(bar); +#else + ContextMenu *contextMenu = new ContextMenu(this); + a_pview->addTo(contextMenu); + if (video_supported) + a_vview->addTo(contextMenu); + a_th_edit->addTo(contextMenu); + a_th_del->addTo(contextMenu); + a_th_add->addTo(contextMenu); + a_send->addTo(contextMenu); + a_settings->addTo(contextMenu); +#endif + + installEventFilter(camera->photo); + installEventFilter(camera->video); + camera->photo->installEventFilter(this); + camera->video->installEventFilter(this); + + // Load the allowable sizes from the camera hardware. + photo_size = camera->videocaptureview->photoSizes(); + video_size = camera->videocaptureview->videoSizes(); + + settings = new CameraSettings(this, 0, TRUE); + // load settings from config + Config cfg("Camera"); + cfg.setGroup("General"); + QString l = cfg.readEntry("location"); + +#warning fixme + /*if ( !l.isEmpty() ) + settings->location->setLocation(l); + */ + + storagepath = settings->location->documentPath(); + cfg.setGroup("Photo"); + int w; + w = cfg.readNumEntry("width", camera->videocaptureview->recommendedPhotoSize().width()); + for (psize = 0; psize < (int) photo_size.count() - 1 && photo_size[psize].width() > w;) + psize++; + pquality = cfg.readNumEntry("quality", settings->photo_quality->value()); + cfg.setGroup("Video"); + w = cfg.readNumEntry("width", camera->videocaptureview->recommendedVideoSize().width()); + for (vsize = 0; vsize < (int) video_size.count() - 1 && video_size[vsize].width() > w;) + vsize++; + vquality = cfg.readNumEntry("quality", settings->video_quality->value()); + vframerate = cfg.readNumEntry("framerate", settings->video_framerate->value()); + + for (int i = 0; i < (int) photo_size.count(); i++) { + settings->photo_size->insertItem(tr("%1 x %2").arg(photo_size[i].width()). + arg(photo_size[i].height())); + } + for (int i = 0; i < (int) video_size.count(); i++) { + settings->video_size->insertItem(tr("%1 x %2").arg(video_size[i].width()). + arg(video_size[i].height())); + } + + namehint = 0; + recording = FALSE; + + preview(); + + if (!video_supported) { + // Room for longer text + camera->photo->setText(tr("Take Photo")); + camera->video->setEnabled(FALSE); + camera->video->hide(); + } +} + +CameraMainWindow::~CameraMainWindow() +{ +} + +void CameraMainWindow::resizeEvent(QResizeEvent *) +{ + thumbw = width() / 5 - 4; + thumbh = thumbw * 3 / 4; + thumb[0]->setFixedHeight(thumbh + thmarg * 2); + loadThumbs(); +} + +bool CameraMainWindow::event(QEvent * e) +{ + if (e->type() == QEvent::WindowActivate) { + if (cur_thumb < 0) + camera->videocaptureview->setLive(); + } + else if (e->type() == QEvent::WindowDeactivate) { + camera->videocaptureview->setLive(-1); + } + return QMainWindow::event(e); +} + +bool CameraMainWindow::eventFilter(QObject * o, QEvent * e) +{ + if (e->type() == QEvent::KeyPress) { + QKeyEvent *ke = (QKeyEvent *) e; + +#if QTOPIA_PHONE + if (!ke->isAutoRepeat()) { + if (ke->key() == Key_1) { + takePhoto(); + return TRUE; + } + else if (ke->key() == Key_2) { + toggleVideo(); + return TRUE; + } + } +#endif + if (ke->key() == Key_Up) { + camera->photo->setFocus(); + return TRUE; + } + else if (ke->key() == Key_Down) { + thumb[0]->setFocus(); + return TRUE; + } + else if (ke->key() == Key_Left) { + if (o == camera->video) { + camera->photo->setFocus(); + return TRUE; + } + else { + if (o == thumb[0]) + return TRUE; + for (int i = 1; i < nthumb; ++i) { + if (o == thumb[i]) { + thumb[i - 1]->setFocus(); + return TRUE; + } + } + } + } + else if (ke->key() == Key_Right) { + if (o == camera->photo) { + camera->video->setFocus(); + return TRUE; + } + else { + if (o == thumb[nthumb - 1]) + return TRUE; + for (int i = 0; i < nthumb - 1; ++i) { + if (o == thumb[i]) { + thumb[i + 1]->setFocus(); + return TRUE; + } + } + } + } + } + else if (e->type() == QEvent::FocusIn) { + if (o == camera->photo) + camera->photo->setText(tr("Take Photo")); + updateActions(); + } + else if (e->type() == QEvent::FocusOut) { + if (o == camera->photo) + camera->photo->setText(tr("Activate Camera")); + } + return QWidget::eventFilter(o, e); +} + +void CameraMainWindow::updateActions() +{ + bool p = FALSE, v = FALSE; + QWidget *foc = focusWidget(); + if (foc == camera->photo) { + p = TRUE; + v = FALSE; + } + else if (foc == camera->video) { + v = TRUE; + p = FALSE; + } + a_pview->setEnabled(p); + a_vview->setEnabled(v); + a_settings->setEnabled(p || v); + bool th = !p && !v; + if (th) { + int i; + for (i = 0; i < nthumb; i++) { + if (thumb[i] == foc) { + selectThumb(i); + break; + } + } + if (i == nthumb || !thumb[i]->pixmap()) + th = FALSE; + } + else { + selectThumb(-1); + } +} + +void CameraMainWindow::viewPictures() +{ +#warning fixme +// ServiceRequest req("PhotoEdit","showCategory(int)"); +// req << camcat; +// req.send(); +} + +void CameraMainWindow::viewVideos() +{ +#warning fixme +// Service::appLnk("Open/video/mpeg").execute(); +} + +void CameraMainWindow::doSettings() +{ + bool v = video_supported; +#ifdef QTOPIA_PHONE + bool p; + p = a_pview->isEnabled(); + v = v && a_vview->isEnabled(); + if (p) + settings->photo->show(); + else + settings->photo->hide(); +#endif + if (v) + settings->video->show(); + else + settings->video->hide(); + settings->photo_size->setCurrentItem(psize); + settings->video_size->setCurrentItem(vsize); + settings->photo_quality->setValue(pquality); + settings->video_quality->setValue(vquality); + settings->video_framerate->setValue(vframerate); + settings->video_quality_n->setFixedWidth(fontMetrics().width("100")); + settings->photo_quality_n->setFixedWidth(fontMetrics().width("100")); + + if (QPEApplication::execDialog(settings)) { + confirmSettings(); + } + else { +#warning fixme +// settings->location->setLocation(storagepath); + } +} + +void CameraMainWindow::confirmSettings() +{ + storagepath = settings->location->documentPath(); + psize = settings->photo_size->currentItem(); + vsize = settings->video_size->currentItem(); + pquality = settings->photo_quality->value(); + vquality = settings->video_quality->value(); + vframerate = settings->video_framerate->value(); + + // save settings + Config cfg("Camera"); + cfg.setGroup("General"); + cfg.writeEntry("location", storagepath); + cfg.setGroup("Photo"); + cfg.writeEntry("width", photo_size[psize].width()); + cfg.writeEntry("quality", pquality); + cfg.setGroup("Video"); + cfg.writeEntry("width", video_size[vsize].width()); + cfg.writeEntry("quality", vquality); + cfg.writeEntry("framerate", vframerate); + + loadThumbs(); + + preview(); +} + +static int cmpDocLnk(const void *a, const void *b) +{ + const DocLnk *la = *(const DocLnk **) a; + const DocLnk *lb = *(const DocLnk **) b; + QFileInfo fa(la->linkFileKnown()? la->linkFile() : la->file()); + QFileInfo fb(lb->linkFileKnown()? lb->linkFile() : lb->file()); + return fa.lastModified().secsTo(fb.lastModified()); +} + +void CameraMainWindow::loadThumbs() +{ + if (storagepath.isEmpty()) { + updateActions(); + return; + } + + DocLnkSet set(storagepath, "image/jpeg"); + const QList < DocLnk > &l = set.children(); + + DocLnk *lnk; + DocLnk **array = new DocLnk *[l.count()]; + int n = 0; + for (QListIterator < DocLnk > it(l); (lnk = it.current()); ++it) { + if (lnk->categories().contains(camcat)) + array[n++] = lnk; + } + qsort(array, n, sizeof(array[0]), cmpDocLnk); + for (int i = 0; i < nthumb; i++) { + QPixmap pm; + if (i < n) { + picturefile[i] = *array[i]; + QImage img = Image::loadScaled(picturefile[i].file(), thumbw, thumbh); + pm.convertFromImage(img); + } + if (pm.isNull()) { + thumb[i]->setText(""); + } + else { + thumb[i]->setPixmap(pm); + } + thumb[i]->setEnabled(!pm.isNull()); + } + if (cur_thumb >= 0) + selectThumb(cur_thumb); + + if (!camera->videocaptureview->available()) { + camera->photo->setEnabled(FALSE); + camera->video->setEnabled(FALSE); + if (!n) { + thumb[0]->setEnabled(FALSE); + } + else { + thumb[0]->setFocus(); + thumb[0]->setEnabled(TRUE); + } + } + + updateActions(); +} + +void CameraMainWindow::delThumb(int th) +{ + switch (QMessageBox::warning(0, tr("Confirmation"), + tr("<qt>Delete '%1'?</qt>", + "%1 = file name").arg(picturefile[th].name()), QMessageBox::Yes, + QMessageBox::No)) { + case QMessageBox::Yes: + picturefile[th].removeFiles(); + + // Rhys Hack - if we have just deleted the last image and there + // is no camera connected, then exit the application. This + // avoids a focus problem where it is impossible to exit with + // the back button due to the focus being in a stupid place. + loadThumbs(); + if (!camera->videocaptureview->available() && !(thumb[0]->isEnabled())) { + close(); + } + break; + default: + //nothing + break; + } +} + +void CameraMainWindow::pushThumb(const DocLnk & f, const QImage & img) +{ + for (int i = nthumb; --i;) { + bool en = thumb[i - 1]->isEnabled(); + thumb[i]->setEnabled(en); + picturefile[i] = picturefile[i - 1]; + const QPixmap *pm = thumb[i - 1]->pixmap(); + if (en && pm) { + thumb[i]->setPixmap(*pm); + } + else { + thumb[i]->setText(""); + } + } + QPixmap pm; + QSize sz = Image::aspectScaleSize(img.width(), img.height(), thumbw, thumbh); + QImage simg = img.smoothScale(sz.width(), sz.height()); + pm.convertFromImage(simg); + thumb[0]->setPixmap(pm); + thumb[0]->setEnabled(TRUE); + picturefile[0] = f; +} + +void CameraMainWindow::takePhoto() +{ + if (camera->photo != focusWidget()) { + camera->photo->setFocus(); + return; + } + QSize size = photo_size[psize]; + if (size == camera->videocaptureview->captureSize() || + camera->videocaptureview->refocusDelay() == 0) { + + // We can grab the current image immediately. + takePhotoNow(); + + } + else { + + // Change the camera size and then wait for the camera to refocus. + camera->videocaptureview->setCaptureSize(size); + refocusTimer->start(camera->videocaptureview->refocusDelay(), TRUE); + + } +} + +void CameraMainWindow::takePhotoNow() +{ + QImage img = camera->videocaptureview->image(); + + if (inSnapMode()) { + QCopEnvelope e(snap_ch, "valueSupplied(QString,QImage)"); + QSize s = Image::aspectScaleSize(img.width(), img.height(), snap_maxw, snap_maxh); + e << snap_id << img.smoothScale(s.width(), s.height()); + setSnapMode(FALSE); + close(); + } + else { + DocLnk f; + //f.setLocation(storagepath); + f.setType("image/jpeg"); + QDateTime dt = QDateTime::currentDateTime(); + QString date = dt.toString(); + f.setName(tr("Photo, " + date)); + + QArray < int >c(1); + c[0] = camcat; + f.setCategories(c); + img.save(f.file(), "JPEG", pquality); // Save the image in its original size. + f.writeLink(); + pushThumb(f, img); + } + + preview(); +} + +bool CameraMainWindow::inSnapMode() const +{ + return !snap_ch.isEmpty(); +} + +void CameraMainWindow::setSnapMode(bool y) +{ + if (y) { + camera->thumbs->hide(); + camera->video->hide(); + } + else { + camera->thumbs->show(); + if (video_supported) + camera->video->show(); + else + camera->video->hide(); + snap_ch = QString::null; + } +} + +void CameraMainWindow::toggleVideo() +{ + if (recording) + stopVideo(); + else + startVideo(); + recording = !recording; + camera->video->setText(recording ? tr("Stop") : tr("Video")); + camera->photo->setEnabled(!recording); + for (int i = 0; i < nthumb; i++) + thumb[i]->setEnabled(!recording && thumb[i]->pixmap()); +} + +void CameraMainWindow::startVideo() +{ + // XXX eg. MJPG +} +void CameraMainWindow::stopVideo() +{ +} + +void CameraMainWindow::thumbClicked(int i) +{ + selectThumb(i); +} + +void CameraMainWindow::editThumb() +{ + picturefile[cur_thumb].execute(); +} + +void CameraMainWindow::selectThumb(int i) +{ + cur_thumb = i; + if (i >= 0) { + QImage img(picturefile[i].file()); + camera->videocaptureview->setStill(img); + thumb[i]->setFocus(); + } + else { + camera->videocaptureview->setLive(); + } + a_th_edit->setEnabled(i >= 0); + a_th_del->setEnabled(i >= 0); + a_th_add->setEnabled(i >= 0); + a_send->setEnabled(i >= 0); +} + +void CameraMainWindow::moveToContact() +{ + if (cur_thumb >= 0) { +#warning fixme +// QCopEnvelope e(Service::channel("Contacts"),"setContactImage(QImage)"); +// QImage img; +// img.load(picturefile[cur_thumb].file()); +// e << img; + } +} + +void CameraMainWindow::delThumb() +{ + if (cur_thumb >= 0) { + int d = cur_thumb; + if (cur_thumb > 0) + selectThumb(cur_thumb - 1); + delThumb(d); + } +} + +void CameraMainWindow::linkChanged(const QString &) +{ + loadThumbs(); +} + +void CameraMainWindow::appMessage(const QCString & msg, const QByteArray & data) +{ + if (msg == "getImage(QCString,QString,int,int,QImage)") { + QDataStream ds(data, IO_ReadOnly); + ds >> snap_ch >> snap_id >> snap_maxw >> snap_maxh; + setSnapMode(TRUE); + QPEApplication::setKeepRunning(); + } +} + +void CameraMainWindow::preview() +{ + if (camera->videocaptureview->refocusDelay() > 200) { + camera->videocaptureview->setCaptureSize(photo_size[psize]); + } + else { + camera->videocaptureview->setCaptureSize(camera->videocaptureview-> + recommendedPreviewSize()); + } +} + +void CameraMainWindow::sendFile() +{ + if (cur_thumb >= 0) { + //copy file + QFile input(picturefile[cur_thumb].file()); + if (!input.open(IO_ReadOnly)) { + return; //error + } + QFile output(picfile); + if (!output.open(IO_WriteOnly)) { + return; + } + + const int BUFFER_SIZE = 1024; + Q_INT8 buffer[BUFFER_SIZE]; + + QDataStream srcStr(&input); + QDataStream destStr(&output); + + while (!srcStr.atEnd()) { + int i = 0; + while (!srcStr.atEnd() && i < BUFFER_SIZE) { + srcStr >> buffer[i]; + i++; + } + for (int k = 0; k < i; k++) { + destStr << buffer[k]; + } + } + +#warning fixme +// QCopEnvelope e(Service::channel("Email"),"writeMessage(QString,QString,QStringList,QStringList)"); +// e << QString() << QString() << QStringList() << QStringList( QString( picfile ) ); + } +} + +void ThumbButton::drawButtonLabel(QPainter * p) +{ + const QPixmap *pm = pixmap(); + if (pm) { + QSize s = (size() - pm->size()) / 2; + p->drawPixmap(s.width(), s.height(), *pm); + } +} + +ThumbButton::ThumbButton(QWidget * parent, const char *name):QToolButton(parent, name) +{ +} + diff --git a/noncore/multimedia/camera2/mainwindow.h b/noncore/multimedia/camera2/mainwindow.h new file mode 100644 index 0000000..d6c5a7e --- a/dev/null +++ b/noncore/multimedia/camera2/mainwindow.h @@ -0,0 +1,132 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "camerabase.h" +#include <qvaluelist.h> +#include <qmainwindow.h> +#include <qpe/applnk.h> + +class LocationCombo; +class QAction; +class QTimer; +class CameraSettings; + + +class CameraMainWindow : public QMainWindow +{ + Q_OBJECT +public: + static QString appName() { return QString::fromLatin1("camera2"); } + + CameraMainWindow( QWidget *parent=0, const char *name=0, WFlags fl=0 ); + ~CameraMainWindow(); + +public slots: + void takePhoto(); + void toggleVideo(); + void selectThumb(int i); + void thumbClicked(int i); + +private slots: + void viewPictures(); + void viewVideos(); + void doSettings(); + void appMessage(const QCString& msg, const QByteArray& data); + void editThumb(); + void delThumb(); + void moveToContact(); + void takePhotoNow(); + void sendFile(); + void linkChanged(const QString&); + +private: + bool event(QEvent* e); + void updateActions(); + void resizeEvent(QResizeEvent*); + + bool eventFilter(QObject*, QEvent*); + QString nextFileName(); + void loadThumbs(); + void pushThumb(const DocLnk& f, const QImage& img); + static const int nthumb = 5; + QToolButton* thumb[nthumb]; + DocLnk picturefile[nthumb]; + int cur_thumb; + void delThumb(int th); + + // Settings + void confirmSettings(); + CameraSettings *settings; + QString storagepath; + int thumbw; + int thumbh; + int psize; + int vsize; + int pquality; + int vquality; + int vframerate; + + // Snap + QCString snap_ch; + QString snap_id; + int snap_maxw, snap_maxh; + bool inSnapMode() const; + void setSnapMode(bool); + + CameraBase *camera; + + int namehint; + QAction *a_pview, *a_vview, *a_settings; + QAction *a_th_edit, *a_th_del, *a_th_add; + QAction *a_send; + QValueList<QSize> photo_size; + QValueList<QSize> video_size; + + QTimer *refocusTimer; + QString picfile; + + bool recording; + void stopVideo(); + void startVideo(); + + void preview(); + + int camcat; +}; + +#endif + diff --git a/noncore/multimedia/camera2/opie-camera2.control b/noncore/multimedia/camera2/opie-camera2.control new file mode 100644 index 0000000..a2d0700 --- a/dev/null +++ b/noncore/multimedia/camera2/opie-camera2.control @@ -0,0 +1,10 @@ +Package: opie-camera2 +Files: bin/camerapics/camera2 apps/Applications/camera2.desktop +Priority: optional +Section: opie/multimedia +Maintainer: Lorn "ljp" Potter <lorn.potter@trolltech.com> +Architecture: arm +Version: 1.0.1$EXTRAVERSION +Depends: libqpe1, libopiecore2, libopieui2 +Description: A Camera Application + A Camera Application to use with Video4Linux. diff --git a/noncore/multimedia/camera2/thumbbutton.h b/noncore/multimedia/camera2/thumbbutton.h new file mode 100644 index 0000000..f7ca3b4 --- a/dev/null +++ b/noncore/multimedia/camera2/thumbbutton.h @@ -0,0 +1,50 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef THUMBBUTTON_H +#define THUMBBUTTON_H + +#include <qtoolbutton.h> + +class ThumbButton : public QToolButton +{ + Q_OBJECT +public: + ThumbButton( QWidget *parent, const char* name ); + + void drawButtonLabel( QPainter * ); +}; + +#endif + diff --git a/noncore/multimedia/camera2/videocaptureview.cpp b/noncore/multimedia/camera2/videocaptureview.cpp new file mode 100644 index 0000000..410634a --- a/dev/null +++ b/noncore/multimedia/camera2/videocaptureview.cpp @@ -0,0 +1,599 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include "videocaptureview.h" +#include <qimage.h> +#include <qpainter.h> +#ifdef Q_WS_QWS +#include <qgfx_qws.h> +#include <qdirectpainter_qws.h> +#endif + +#ifdef __linux__ +#define HAVE_VIDEO4LINUX 1 +#endif + +#ifdef HAVE_VIDEO4LINUX + +#include <sys/types.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <fcntl.h> +#include <linux/videodev.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <sys/mman.h> + +#endif /* HAVE_VIDEO4LINUX */ + +class VideoCapture { + public: + VideoCapture(); + ~VideoCapture(); + + bool hasCamera() const; + void getCameraImage(QImage & img, bool copy = FALSE); + + QValueList < QSize > photoSizes() const; + QValueList < QSize > videoSizes() const; + + QSize recommendedPhotoSize() const; + QSize recommendedVideoSize() const; + QSize recommendedPreviewSize() const; + + QSize captureSize() const; + void setCaptureSize(QSize size); + + uint refocusDelay() const; + int minimumFramePeriod() const; + + private: +#ifdef HAVE_VIDEO4LINUX + int fd; + int width, height; + struct video_capability caps; + struct video_mbuf mbuf; + unsigned char *frames; + int currentFrame; + + void setupCamera(QSize size); + void shutdown(); +#endif +}; + +#ifdef HAVE_VIDEO4LINUX + +#define VIDEO_DEVICE "/dev/video" + +bool VideoCapture::hasCamera() const +{ + return (fd != -1); +} + +QSize VideoCapture::captureSize() const +{ + return QSize(width, height); +} + +uint VideoCapture::refocusDelay() const +{ + return 250; +} + +int VideoCapture::minimumFramePeriod() const +{ + return 40; // milliseconds +} + +VideoCapture::VideoCapture() +{ + setupCamera(QSize(0, 0)); +} + +VideoCapture::~VideoCapture() +{ + shutdown(); +} + +void VideoCapture::setupCamera(QSize size) +{ + qWarning(" VideoCapture::setupCamera"); + // Clear important variables. + frames = 0; + currentFrame = 0; + width = 640; + height = 480; + caps.minwidth = width; + caps.minheight = height; + caps.maxwidth = width; + caps.maxheight = height; + + // Open the video device. + fd = open(VIDEO_DEVICE, O_RDWR); + if (fd == -1) { + qWarning("%s: %s", VIDEO_DEVICE, strerror(errno)); + return; + } + + // Get the device's current capabilities. + memset(&caps, 0, sizeof(caps)); + if (ioctl(fd, VIDIOCGCAP, &caps) < 0) { + qWarning("%s: could not retrieve the video capabilities", VIDEO_DEVICE); + close(fd); + fd = -1; + return; + } + + // Change the channel to the first-connected camera, skipping TV inputs. + // If there are multiple cameras, this may need to be modified. + int chan; + struct video_channel chanInfo; + qWarning("available video capture inputs:"); + for (chan = 0; chan < caps.channels; ++chan) { + chanInfo.channel = chan; + if (ioctl(fd, VIDIOCGCHAN, &chanInfo) >= 0) { + if (chanInfo.type == VIDEO_TYPE_CAMERA) + qWarning(" %s (camera)", chanInfo.name); + else if (chanInfo.type == VIDEO_TYPE_TV) + qWarning(" %s (tv)", chanInfo.name); + else + qWarning(" %s (unknown)", chanInfo.name); + } + } + for (chan = 0; chan < caps.channels; ++chan) { + chanInfo.channel = chan; + if (ioctl(fd, VIDIOCGCHAN, &chanInfo) >= 0) { + if (chanInfo.type == VIDEO_TYPE_CAMERA) { + qWarning("selecting camera on input %s", chanInfo.name); + if (ioctl(fd, VIDIOCSCHAN, &chan) < 0) { + qWarning("%s: could not set the channel", VIDEO_DEVICE); + } + break; + } + } + } + + // Set the desired picture mode to RGB32. + struct video_picture pict; + memset(&pict, 0, sizeof(pict)); + ioctl(fd, VIDIOCGPICT, &pict); + pict.palette = VIDEO_PALETTE_RGB32; + if (ioctl(fd, VIDIOCSPICT, &pict) < 0) { + qWarning("%s: could not set the picture mode", VIDEO_DEVICE); + close(fd); + fd = -1; + return; + } + + // Determine the capture size to use. Zero indicates "preview mode". + if (size.width() == 0) { + size = QSize(caps.minwidth, caps.minheight); + } + + // Get the current capture window. + struct video_window wind; + memset(&wind, 0, sizeof(wind)); + ioctl(fd, VIDIOCGWIN, &wind); + + // Adjust the capture size to match the camera's aspect ratio. + if (caps.maxwidth > 0 && caps.maxheight > 0) { + if (size.width() > size.height()) { + size = QSize(size.height() * caps.maxwidth / caps.maxheight, size.height()); + } + else { + size = QSize(size.width(), size.width() * caps.maxheight / caps.maxwidth); + } + } + + // Set the new capture window. + wind.x = 0; + wind.y = 0; + wind.width = size.width(); + wind.height = size.height(); + if (ioctl(fd, VIDIOCSWIN, &wind) < 0) { + qWarning("%s: could not set the capture window", VIDEO_DEVICE); + } + + // Re-read the capture window, to see what it was adjusted to. + ioctl(fd, VIDIOCGWIN, &wind); + width = wind.width; + height = wind.height; + + // Enable mmap-based access to the camera. + memset(&mbuf, 0, sizeof(mbuf)); + if (ioctl(fd, VIDIOCGMBUF, &mbuf) < 0) { + qWarning("%s: mmap-based camera access is not available", VIDEO_DEVICE); + close(fd); + fd = -1; + return; + } + + // Mmap the designated memory region. + frames = (unsigned char *) mmap(0, mbuf.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (!frames || frames == (unsigned char *) (long) (-1)) { + qWarning("%s: could not mmap the device", VIDEO_DEVICE); + close(fd); + fd = -1; + return; + } + + // Start capturing of the first frame. + struct video_mmap capture; + currentFrame = 0; + capture.frame = currentFrame; + capture.width = width; + capture.height = height; + capture.format = VIDEO_PALETTE_RGB32; + ioctl(fd, VIDIOCMCAPTURE, &capture); +} + +void VideoCapture::shutdown() +{ + if (frames != 0) { + munmap(frames, mbuf.size); + frames = 0; + } + if (fd != -1) { + int flag = 0; + ioctl(fd, VIDIOCSYNC, 0); + ioctl(fd, VIDIOCCAPTURE, &flag); + close(fd); + fd = -1; + } +} + +void VideoCapture::getCameraImage(QImage & img, bool copy) +{ + if (fd == -1) { + if (img.isNull()) { + img.create(width, height, 32); + } + return; + } + + // Start capturing the next frame (we alternate between 0 and 1). + int frame = currentFrame; + struct video_mmap capture; + if (mbuf.frames > 1) { + currentFrame = !currentFrame; + capture.frame = currentFrame; + capture.width = width; + capture.height = height; + capture.format = VIDEO_PALETTE_RGB32; + ioctl(fd, VIDIOCMCAPTURE, &capture); + } + + // Wait for the current frame to complete. + ioctl(fd, VIDIOCSYNC, &frame); + + // Create an image that refers directly to the kernel's + // frame buffer, to avoid having to copy the data. + if (!copy) { + img = QImage(frames + mbuf.offsets[frame], width, height, 32, 0, 0, QImage::IgnoreEndian); + } + else { + img.create(width, height, 32); + memcpy(img.bits(), frames + mbuf.offsets[frame], width * height * 4); + } + + // Queue up another frame if the device only supports one at a time. + if (mbuf.frames <= 1) { + capture.frame = currentFrame; + capture.width = width; + capture.height = height; + capture.format = VIDEO_PALETTE_RGB32; + ioctl(fd, VIDIOCMCAPTURE, &capture); + } +} + +QValueList < QSize > VideoCapture::photoSizes() const +{ + QValueList < QSize > list; + list.append(QSize(caps.maxwidth, caps.maxheight)); + if (caps.maxwidth != caps.minwidth || caps.maxheight != caps.minheight) + list.append(QSize(caps.minwidth, caps.minheight)); + return list; +} + +QValueList < QSize > VideoCapture::videoSizes() const +{ + // We use the same sizes for both. + return photoSizes(); +} + +QSize VideoCapture::recommendedPhotoSize() const +{ + return QSize(caps.maxwidth, caps.maxheight); +} + +QSize VideoCapture::recommendedVideoSize() const +{ + return QSize(caps.minwidth, caps.minheight); +} + +QSize VideoCapture::recommendedPreviewSize() const +{ + return QSize(caps.minwidth, caps.minheight); +} + +void VideoCapture::setCaptureSize(QSize size) +{ + if (size.width() != width || size.height() != height) { + shutdown(); + setupCamera(size); + } +} + +#else /* !HAVE_VIDEO4LINUX */ + +// Dummy implementation for systems without video. + +VideoCapture::VideoCapture() +{ +} + +VideoCapture::~VideoCapture() +{ +} + +bool VideoCapture::hasCamera() const +{ + return TRUE; +} + +QSize VideoCapture::captureSize() const +{ + return QSize(640, 480); +} + +uint VideoCapture::refocusDelay() const +{ + return 0; +} + +int VideoCapture::minimumFramePeriod() const +{ + return 100; +} + +static unsigned int nextrand() +{ +#define A 16807 +#define M 2147483647 +#define Q 127773 +#define R 2836 + static unsigned int rnd = 1; + unsigned long hi = rnd / Q; + unsigned long lo = rnd % Q; + unsigned long test = A * lo - R * hi; + if (test > 0) + rnd = test; + else + rnd = test + M; + return rnd; +} + +void VideoCapture::getCameraImage(QImage & img, bool) +{ + // Just generate something dynamic (rectangles) + static QImage cimg; + int x, y, w, h; + if (cimg.isNull()) { + x = y = 0; + w = 640; + h = 480; + cimg.create(w, h, 32); + } + else { + w = nextrand() % (cimg.width() - 10) + 10; + h = nextrand() % (cimg.height() - 10) + 10; + x = nextrand() % (cimg.width() - w); + y = nextrand() % (cimg.height() - h); + } + QRgb c = qRgb(nextrand() % 255, nextrand() % 255, nextrand() % 255); + for (int j = 0; j < h; j++) { + QRgb *l = (QRgb *) cimg.scanLine(y + j) + x; + for (int i = 0; i < w; i++) + l[i] = c; + } + img = cimg; +} + +QValueList < QSize > VideoCapture::photoSizes() constconst +{ + QValueList < QSize > list; + list.append(QSize(640, 480)); + list.append(QSize(320, 240)); + return list; +} + +QValueList < QSize > VideoCapture::videoSizes() constconst +{ + QValueList < QSize > list; + list.append(QSize(640, 480)); + list.append(QSize(320, 240)); + return list; +} + +QSize VideoCapture::recommendedPhotoSize() const +{ + return QSize(640, 480); +} + +QSize VideoCapture::recommendedVideoSize() const +{ + return QSize(320, 240); +} + +QSize VideoCapture::recommendedPreviewSize() const +{ + return QSize(320, 240); +} + +void VideoCapture::setCaptureSize(QSize size) +{ +} + +#endif /* !HAVE_VIDEO4LINUX */ + +VideoCaptureView::VideoCaptureView(QWidget * parent, const char *name, WFlags fl):QWidget(parent, + name, fl) +{ + capture = new VideoCapture(); + QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Expanding); + setSizePolicy(sp); + tid_update = 0; + setLive(); +} + +VideoCaptureView::~VideoCaptureView() +{ + delete capture; +} + +void VideoCaptureView::setLive(int period) +{ + if (tid_update) + killTimer(tid_update); + if (period == 0) + tid_update = startTimer(capture->minimumFramePeriod()); + else if (period > 0) + tid_update = startTimer(period); + else + tid_update = 0; +} + +void VideoCaptureView::setStill(const QImage & i) +{ + setLive(-1); + img = i; + repaint(TRUE); +} + +QValueList < QSize > VideoCaptureView::photoSizes() const +{ + return capture->photoSizes(); +} + +QValueList < QSize > VideoCaptureView::videoSizes() const +{ + return capture->videoSizes(); +} + +QSize VideoCaptureView::recommendedPhotoSize() const +{ + return capture->recommendedPhotoSize(); +} + +QSize VideoCaptureView::recommendedVideoSize() const +{ + return capture->recommendedVideoSize(); +} + +QSize VideoCaptureView::recommendedPreviewSize() const +{ + return capture->recommendedPreviewSize(); +} + +QSize VideoCaptureView::captureSize() const +{ + return capture->captureSize(); +} + +void VideoCaptureView::setCaptureSize(QSize size) +{ + capture->setCaptureSize(size); +} + +uint VideoCaptureView::refocusDelay() const +{ + return capture->refocusDelay(); +} + +bool VideoCaptureView::available() const +{ + return capture->hasCamera(); +} + +void VideoCaptureView::paintEvent(QPaintEvent *) +{ + if (tid_update && !capture->hasCamera()) { + QPainter p(this); + p.drawText(rect(), AlignCenter, tr("No Camera")); + return; + } + + if (tid_update) + capture->getCameraImage(img); + int w = img.width(); + int h = img.height(); + + if (!w || !h) + return; + + if (width() * w > height() * h) { + w = w * height() / h; + h = height(); + } + else { + h = h * width() / w; + w = width(); + } + + if (qt_screen->transformOrientation() == 0) { + // Stretch and draw the image. + QDirectPainter p(this); + QGfx *gfx = p.internalGfx(); + if (gfx) { + gfx->setSource(&img); + gfx->setAlphaType(QGfx::IgnoreAlpha); + gfx->stretchBlt((width() - w) / 2, (height() - h) / 2, w, h, img.width(), img.height()); + } + } + else { + // This code is nowhere near efficient enough (hence the above). + // TODO - handle rotations during direct painting. + QImage scimg = img.smoothScale(w, h); + QPainter p(this); + p.drawImage((width() - w) / 2, (height() - h) / 2, scimg); + } +} + +void VideoCaptureView::timerEvent(QTimerEvent *) +{ + repaint(FALSE); +} + diff --git a/noncore/multimedia/camera2/videocaptureview.h b/noncore/multimedia/camera2/videocaptureview.h new file mode 100644 index 0000000..68c3b68 --- a/dev/null +++ b/noncore/multimedia/camera2/videocaptureview.h @@ -0,0 +1,82 @@ +/********************************************************************** +** Copyright (C) 2000-2006 Trolltech AS. All rights reserved. +** +** This file is part of the Qtopia Environment. +** +** 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. +** +** A copy of the GNU GPL license version 2 is included in this package as +** LICENSE.GPL. +** +** 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. +** +** In addition, as a special exception Trolltech gives permission to link +** the code of this program with Qtopia applications copyrighted, developed +** and distributed by Trolltech under the terms of the Qtopia Personal Use +** License Agreement. You must comply with the GNU General Public License +** in all respects for all of the code used other than the applications +** licensed under the Qtopia Personal Use License Agreement. If you modify +** this file, you may extend this exception to your version of the file, +** but you are not obligated to do so. If you do not wish to do so, delete +** this exception statement from your version. +** +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ +#ifndef VIDEOVIEW_H +#define VIDEOVIEW_H + +#include <qwidget.h> +#include <qimage.h> +#include <qvaluelist.h> + +class VideoCapture; + + +class VideoCaptureView : public QWidget +{ + Q_OBJECT + +public: + VideoCaptureView( QWidget *parent=0, const char *name=0, WFlags fl=0 ); + ~VideoCaptureView(); + + bool available() const; + + QImage image() const { return img; } + void setLive(int period=0); + void setStill(const QImage&); + + QValueList<QSize> photoSizes() const; + QValueList<QSize> videoSizes() const; + + QSize recommendedPhotoSize() const; + QSize recommendedVideoSize() const; + QSize recommendedPreviewSize() const; + + QSize captureSize() const; + void setCaptureSize( QSize size ); + + uint refocusDelay() const; + +protected: + void paintEvent(QPaintEvent*); + void timerEvent(QTimerEvent*); + +private: + QImage img; + int tid_update; + VideoCapture *capture; +}; + +#endif + |