diff options
| author | deva <deva> | 2006-03-04 14:53:17 +0000 | 
|---|---|---|
| committer | deva <deva> | 2006-03-04 14:53:17 +0000 | 
| commit | f02095ee5ceb78f1781a9e250693b8866ca42181 (patch) | |
| tree | 7953c6b5f004f31ee9b340d7cdff5e85890594fc /client | |
| parent | 71c713dce2b5128862b293aa7fcc1d7ee89ffaf1 (diff) | |
*** empty log message ***
Diffstat (limited to 'client')
33 files changed, 4959 insertions, 0 deletions
| diff --git a/client/aboutwindow.cc b/client/aboutwindow.cc new file mode 100644 index 0000000..8743ed8 --- /dev/null +++ b/client/aboutwindow.cc @@ -0,0 +1,92 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            aboutwindow.cc + * + *  Sun Aug 22 21:57:49 2004 + *  Copyright  2004  deva + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI +  +#include "aboutwindow.h" + +#include <qpainter.h> +#include <qfont.h> + +#include <config.h> + +#define MARGIN 12 +AboutWindow::AboutWindow( QWidget* parent, const char* name ) +	: QDialog( parent, name ) +{ +	setModal(true); +	pix_about = new QPixmap(); +	pix_about->load( PIXMAP_ABOUT ); + +	resize(pix_about->width(), pix_about->height()); +   +  setBackgroundColor(QColor(200,200,200)); +	 +  btn_ok = new QPushButton(this); +	btn_ok->setText("OK"); +  btn_ok->resize( 140, 50 ); +	btn_ok->move(pix_about->width() - btn_ok->width() - MARGIN, pix_about->height() - btn_ok->height() - MARGIN); +  btn_ok->setFont( QFont( "Arial", 12, QFont::Bold ) ); +   +  QObject::connect( btn_ok, SIGNAL(clicked()), this, SLOT(close()) ); +   +	show(); +} + +AboutWindow::~AboutWindow() +{ +} + +void AboutWindow::mouseReleaseEvent(QMouseEvent *event) +{ +  close(); +} + +void AboutWindow::paintEvent( QPaintEvent *event ) +{ +  int version_x = 58; +  int version_y = 90; + +	if(!event) return; // Just to get rid og the compile warning! +	QPainter painter; +	painter.begin(this); + +  // Draw background +	painter.drawPixmap(0,0, *pix_about); + +  // Draw title and version +	painter.setBrush( SolidPattern );     +	painter.setFont( QFont( "Arial", 18, QFont::Bold ) ); +	painter.setPen( Qt::black ); +	painter.drawText(version_x, version_y, "MIAV-Grab v" VERSION); +	painter.setPen( Qt::red ); +	painter.drawText(version_x + 2, version_y + 2, "MIAV-Grab v" VERSION); + +	painter.end(); +} + +#endif /*USE_GUI*/ diff --git a/client/aboutwindow.h b/client/aboutwindow.h new file mode 100644 index 0000000..f87a10e --- /dev/null +++ b/client/aboutwindow.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            aboutwindow.h + * + *  Sun Aug 22 21:58:22 2004 + *  Copyright  2004  deva + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +  +#ifndef __ABOUTWINDOW_H__ +#define __ABOUTWINDOW_H__ + +#include <qdialog.h> +//#include <qlabel.h> +#include <qpixmap.h> +//#include <qtextedit.h> +#include <qpushbutton.h> + +#define PIXMAP_ABOUT     PIXMAPS"/about.png" +/* +#define ABOUT_INFO "\ +Official homepage:\n\ +    http://www.aasimon.org/miav\n\ +Author:\n\ +    Bent Bisballe (deva@aasimon.org)\n\ +Copyright (c) 2004" + +#define GPL_LICENSE "\ +This program is free software; you can\n\ +redistribute it and/or modify it under the terms\n\ +of the GNU General Public License as published\n\ +by the Free Software Foundation; either version\n\ +2 of the License, or (at your option) any later\n\ +version.\n\ +   This program is distributed in the hope that\n\ +it will be useful, but WITHOUT ANY WARRANTY;\n\ +without even the implied warranty of\n\ +MERCHANTABILITY or FITNESS FOR A PARTI-\n\ +CULAR PURPOSE. See the GNU Library General\n\ +Public License for more details.\n\ +    You should have received a copy of the GNU\n\ +General Public License along with this program;\n\ +if not, write to the Free Software Foundation,\n\ +Inc., 59 Temple Place - Suite 330, Boston,\n\ +MA 02111-1307, USA." +*/ +class AboutWindow : public QDialog +{ +	Q_OBJECT +public: +	AboutWindow(QWidget* parent = 0, const char* name = 0); +	~AboutWindow(); +	virtual void paintEvent( QPaintEvent *event ); +  void mouseReleaseEvent(QMouseEvent *event); + +private: +	QPushButton *btn_ok; +	QPixmap		*pix_about; +}; + +#endif /* __ABOUTWINDOW_H__ */ + +#endif /*USE_GUI*/ diff --git a/client/camera.cc b/client/camera.cc new file mode 100644 index 0000000..5dbec13 --- /dev/null +++ b/client/camera.cc @@ -0,0 +1,182 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            camera.cc + * + *  Fri Oct 29 12:46:38 CEST 2004 + *  Copyright  2004 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "camera.h" + +Camera::Camera(Info *ginfo) +{ +  info = ginfo; +} + +void Camera::connect(const char *ip, const int port, int width, int height) +{ +  initialized = false; + +  pthread_mutex_init (&mutex, NULL); +  //mutex = PTHREAD_MUTEX_INITIALIZER; + +  running = 1; + +	encode_queue = new Queue<Frame>(); // infinite size +	player_queue = new Queue<Frame>(1); // fixed size of 1 + +	sem_init(&encode_sem, 0, 0); +	sem_init(&player_sem, 0, 0); + +	decoder = new Decoder(info, +                        &encode_sem, +                        &player_sem, +                        encode_queue, +                        player_queue, +                        &mutex, +                        &running); + +	encoder = new Encoder(info, +                        ip, port, +                        &encode_sem, +                        encode_queue, +                        &mutex, +                        &running); + +	player = new Player(info, +                      width, height, +                      &running, +                      &player_sem, +                      player_queue, +                      &mutex); + +  decoder->run(); +  encoder->run(); +  player->run(); + +  initialized = true; +} + +Camera::~Camera() +{ +  // Signal to the threads to stop +  running = 0; + +  // Wait for the threads to stop +  decoder->wait_stop(); +  encoder->wait_stop(); +  player->wait_stop(); + +	delete decoder; +	delete encoder; +	delete player; + +	sem_destroy(&encode_sem); +	sem_destroy(&player_sem); + +	delete player_queue; +	delete encode_queue; +} + +void Camera::setCpr(char *newcpr, char* name) +{ +   +  if(initialized) { +    encoder->setCpr(newcpr); +    player->setCpr(newcpr, name); // For the text overlay +  } else { +    info->error("Camera not initialized."); +  } +} + + +void Camera::start() +{ +  if(initialized) {  +    player->startrecord(); // For the text overlay +    encoder->start(); +    decoder->start(); +  } else { +    info->error("Camera not initialized."); +  } +} + +void Camera::stop(n_savestate save) +{ +  if(initialized) { +    player->stoprecord(); // For the textoverlay +    encoder->stop(save); +    decoder->stop(save); +  } else { +    info->error("Camera not initialized."); +  } +} + +void Camera::freeze() +{ +  if(initialized) { +    player->stop(); +    decoder->freeze(); +  } else { +    info->error("Camera not initialized."); +  } +} + +void Camera::unfreeze() +{ +  if(initialized) { +    player->start(); +    decoder->unfreeze(); +  } else { +    info->error("Camera not initialized."); +  } +} + +void Camera::snapshot(unsigned char *rgb) +{ +  if(initialized) { +    decoder->shoot(rgb); +    encoder->shoot(); +  } else { +    info->error("Camera not initialized."); +  } +} + +int Camera::getQueueLength() +{ +  return encode_queue->length(); +} + +void Camera::resize(int w, int h, bool s) +{ +  player->resize(w,h,s); +} + +void Camera::setMute(bool mute) +{ +  decoder->setMute(mute); +  player->setMute(mute); +} + +#endif/* USE_GUI */ diff --git a/client/camera.h b/client/camera.h new file mode 100644 index 0000000..a0b849a --- /dev/null +++ b/client/camera.h @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            camera.h + * + *  Fri Oct 29 12:46:38 CEST 2004 + *  Copyright  2004 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __CAMERA_H__ +#define __CAMERA_H__ + +#include <string> +using namespace std; +#include "info.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +//#include <avformat.h> + +#include "util.h" +#include "queue.h" +#include "decoder.h" +#include "encoder.h" +#include "player.h" +#include "package.h" + +#include "thread.h" +#include "frame.h" + +#include <qwidget.h> + +/** + * This class represents the symbolic representation of the camera and  + * the network functionality. + */ +class Camera { +public: +  Camera(Info *ginfo); +  ~Camera(); +  void connect(const char *ip, +               const int port, +               int width, int height); + +  void setCpr(char *newcpr, char* name); + +  // Camera actions +  void start(); +  void stop(n_savestate save); +  void freeze(); +  void unfreeze(); +  void snapshot(unsigned char *rgb); + +  int getQueueLength(); + +  // Indirect call to player->resize +  void resize(int width, int height, bool showtext); + +  void setMute(bool mute); + +private: +  // Info object passed to all sub objects. +  Info *info; +  bool initialized; + +  /* // No need for these anymore +	pthread_t playertid; +	pthread_t decodetid; +	pthread_t encodetid; +  */ +	volatile int running; + +  Encoder *encoder; +  Decoder *decoder; +  Player *player; + +  Queue<Frame> *encode_queue; +  Queue<Frame> *player_queue; +  sem_t encode_sem; +  sem_t player_sem; +  pthread_mutex_t mutex;// = PTHREAD_MUTEX_INITIALIZER; +}; + + +#endif/*__CAMERA_H__*/ + +#endif/* USE_GUI */ diff --git a/client/config.h b/client/config.h new file mode 100644 index 0000000..e7101c9 --- /dev/null +++ b/client/config.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            config.h + * + *  Thu Jul 28 12:46:38 CEST 2005 + *  Copyright  2004 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ + +#ifndef __CONFIG_IS_LOADED__ +#define __CONFIG_IS_LOADED__ + +#include "../config.h" + +#endif/*__CONFIG_IS_LOADED__*/ diff --git a/client/cprlisten.cc b/client/cprlisten.cc new file mode 100644 index 0000000..0a4958e --- /dev/null +++ b/client/cprlisten.cc @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: tab; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            cprlisten.cc + * + *  Tue Dec 27 17:05:42 CET 2005 + *  Copyright  2005 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of the Aasimon c++ framework. + * + *    This 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. + * + *    It 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 it; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ + +#include "cprlisten.h" +#include "aa_socket.h" + +#include <iostream> +#include <string> +using namespace std; + +#define MAGIC_STOP_STRING "SHUTTHEFUCKUP" + +CPRListen::CPRListen(Info *info, unsigned short port) +{ +	this->info = info; +	this->port = port; +	cpr = "N/A"; +	cprchanged = false; +	running = true; +} + +CPRListen::~CPRListen() +{ +} + +void CPRListen::stop() +{ +	running = false; +	try { +		AASocket socket; +		socket.connect("localhost", port); +		socket.send_string(MAGIC_STOP_STRING); +	} catch(Network_error &e) { +		info->error("In stop(): %s.", e.error.c_str()); +	} +} + +void CPRListen::thread_main() +{ +	info->log("Listening for CPRs."); +	while(running) { +		try { +			string newcpr; +			AASocket socket; +			socket.listen(port); +			newcpr = socket.receive_string(); + + 			if(newcpr == MAGIC_STOP_STRING) { +				running = false; +			}	else { +				mutex.lock(); +				cprchanged = true; +				cpr = newcpr; +				mutex.unlock(); +				info->log("Got CPR: %s.", cpr.c_str()); +			} + +		} catch(Network_error &e) { +			info->error("In thread_main(): %s.", e.error.c_str()); +			running = false; +		} +	} +	info->log("Stopped listening for CPRs."); +} + +bool CPRListen::cprChanged() +{ +	return cprchanged; +} + +string CPRListen::getCpr() +{ +	string cpr_copy; + +	mutex.lock(); +	cpr_copy = cpr; +	mutex.unlock(); + +	cprchanged = false; + +	return cpr_copy; +} diff --git a/client/cprlisten.h b/client/cprlisten.h new file mode 100644 index 0000000..012fe4c --- /dev/null +++ b/client/cprlisten.h @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: tab; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            cprlisten.h + * + *  Tue Dec 27 17:05:42 CET 2005 + *  Copyright  2005 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of the Aasimon c++ framework. + * + *    This 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. + * + *    It 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 it; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ + +#ifndef __AASIMON_FRAMEWORK_CPRLISTEN_H__ +#define __AASIMON_FRAMEWORK_CPRLISTEN_H__ + +#include <string> + +#include "thread.h" +#include "mutex.h" + +#include "aa_socket.h" +#include "info.h" + +class CPRListen: public Thread { +public: +	CPRListen(Info *info, unsigned short port); +	~CPRListen(); + +	bool cprChanged(); +	std::string getCpr(); +	void thread_main(); +	 +	void stop(); // Stops the call to listen + +private: +	Info *info; + +	volatile bool running; +	AASocket *socket; + +	bool cprchanged; +	unsigned short port; +	std::string cpr; +	Mutex mutex; +}; + +#endif/*__AASIMON_FRAMEWORK_CPRLISTEN_H__*/ diff --git a/client/cprquerydialog.cc b/client/cprquerydialog.cc new file mode 100644 index 0000000..19337a4 --- /dev/null +++ b/client/cprquerydialog.cc @@ -0,0 +1,486 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            cprquerydialog.cc + * + *  Sat Feb 19 17:05:43 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include <qframe.h> + +#include "messagebox.h" +#include "cprquerydialog.h" +#include "miav_config.h" + +CPRQueryDialog::CPRQueryDialog(Info *info, +                               QLabel *lcpr, +                               QLabel *lname, +                               QWidget *parent,  +                               const char *name,  +                               QStatusBar *status) +	: QDialog(parent, name, TRUE) +{ +  this->info = info; +  setCaption(name); + +  // Load image +  QPixmap pix_backspace; +  pix_backspace.load( PIXMAP_BACKSPACE ); + +  lbl_name = lname; +  lbl_cpr = lcpr; +  statusbar = status; + +  //Read configuration +  CPR_HOST = config->readString("cpr_host"); +  CPR_PORT = config->readInt("cpr_port"); +  CPR_TIMEOUT = config->readInt("cpr_timeout"); + +  cpr[0] = '\0'; +  internalCpr[0] = '\0';	 + +  cprSocket = new QSocket(this); +  connect(cprSocket, SIGNAL(readyRead()), SLOT(cprSocket_readyRead())); +  connect(cprSocket, SIGNAL(connected()), SLOT(cprSocket_connected())); +  connect(cprSocket, SIGNAL(error(int)), SLOT(cprSocket_error(int))); + +  lbl_cpr->setText("Indtast CPR"); + +  // Setup connection timer +  timer = new QTimer(this); +  connect(timer, SIGNAL(timeout()), SLOT(cprSocket_timeout())); + +  // Generate input buttons +	QGridLayout *gl = new QGridLayout(this, 4, 3, 10, 2); + +	QButton *b1 =  createButton(this, "1", 1); +	QButton *b2 =  createButton(this, "2", 2); +	QButton *b3 =  createButton(this, "3", 3); +	QButton *b4 =  createButton(this, "4", 4); +	QButton *b5 =  createButton(this, "5", 5); +	QButton *b6 =  createButton(this, "6", 6); +	QButton *b7 =  createButton(this, "7", 7); +	QButton *b8 =  createButton(this, "8", 8); +	QButton *b9 =  createButton(this, "9", 9); +	QButton *b0 =  createButton(this, "0", 0); +	QButton *bbs = createButton(this, "", 10); +  bbs->setPixmap(pix_backspace); +	QButton *bca = createButton(this, "CA", 11); + +	gl->addWidget(b1, 0,0); +	gl->addWidget(b2, 0,1); +	gl->addWidget(b3, 0,2); +	gl->addWidget(b4, 1,0); +	gl->addWidget(b5, 1,1); +	gl->addWidget(b6, 1,2); +	gl->addWidget(b7, 2,0); +	gl->addWidget(b8, 2,1); +	gl->addWidget(b9, 2,2); +	gl->addWidget(b0, 3,1); +	gl->addWidget(bbs, 3,2); +	gl->addWidget(bca, 3,0); + +	// Setup signals +	connect(b1, SIGNAL(clicked()), SLOT(b_1_clicked())); +	connect(b2, SIGNAL(clicked()), SLOT(b_2_clicked())); +	connect(b3, SIGNAL(clicked()), SLOT(b_3_clicked())); +	connect(b4, SIGNAL(clicked()), SLOT(b_4_clicked())); +	connect(b5, SIGNAL(clicked()), SLOT(b_5_clicked())); +	connect(b6, SIGNAL(clicked()), SLOT(b_6_clicked())); +	connect(b7, SIGNAL(clicked()), SLOT(b_7_clicked())); +	connect(b8, SIGNAL(clicked()), SLOT(b_8_clicked())); +	connect(b9, SIGNAL(clicked()), SLOT(b_9_clicked())); +	connect(b0, SIGNAL(clicked()), SLOT(b_0_clicked())); +	connect(bbs,SIGNAL(clicked()), SLOT(b_b_clicked())); +	connect(bca,SIGNAL(clicked()), SLOT(b_c_clicked())); +	 +	this->move(175,150); + +  listen = new CPRListen(info, config->readInt("cprlisten_port")); +  listen_timer = new QTimer(this); +  connect(listen_timer, SIGNAL(timeout()), SLOT(listen_timeout())); +  listen->run(); +  listen_timer->start(500); // Check every 500 ms + +  show(); +} + +CPRQueryDialog::~CPRQueryDialog() +{ +  // Cleanup +  //  delete timer; +  //  delete cprSocket + +  // Cleanup after cpr listen +  listen->stop(); +  //  listen->wait_stop(); +  delete listen; +  //  delete listen_timer; +} + +void CPRQueryDialog::listen_timeout() +{ +  string newcpr; +  if(listen->cprChanged()) { +    char newcpr_buf[32]; +    newcpr = listen->getCpr(); +    sprintf(newcpr_buf, "%s-%s", newcpr.substr(0,6).c_str(), newcpr.substr(6,4).c_str()); +    //    printf("cprbuf[%s]\n", newcpr_buf); +    lbl_cpr->setText(newcpr_buf); +    verifycpr(newcpr_buf); +  } +} + +/** + * createButton: + * A genric button-creater  + */ +QPushButton *CPRQueryDialog::createButton(QWidget *parent, const char *text, int value)  +{ +  char buf[32]; +  sprintf(buf, "%d", value); +  QPushButton *q = new QPushButton(this, buf); +   +	QFont f("Lucida", 48); +	q->setFixedSize(150, 100); +	q->setText(text); +	q->setFont(f); +	return q; +} + +/** + * Event functions for handling buttonclicks. + * For button 0-9 the values is sent back. + * Backspace and clear are handled via special + * signals. + * When 10 digits has been input we close the form + */ +void CPRQueryDialog::b_1_clicked() { insert_digit(1); } +void CPRQueryDialog::b_2_clicked() { insert_digit(2); } +void CPRQueryDialog::b_3_clicked() { insert_digit(3); } +void CPRQueryDialog::b_4_clicked() { insert_digit(4); } +void CPRQueryDialog::b_5_clicked() { insert_digit(5); } +void CPRQueryDialog::b_6_clicked() { insert_digit(6); } +void CPRQueryDialog::b_7_clicked() { insert_digit(7); } +void CPRQueryDialog::b_8_clicked() { insert_digit(8); } +void CPRQueryDialog::b_9_clicked() { insert_digit(9); } +void CPRQueryDialog::b_0_clicked() { insert_digit(0);} +void CPRQueryDialog::b_b_clicked() { remove_digit();} +void CPRQueryDialog::b_c_clicked() { remove_all();} + +void CPRQueryDialog::b_clicked(int value)  +{ +  printf("%d\n", value); +	switch(value) { +		case 10: +			if (digits>0) digits--; +			emit bbs_clicked(); +			break; +		case 11: +			digits = 0; +			emit bca_clicked(); +			break; +		default: +			digits++; +			emit number_clicked(value); +	}		 +	if (digits == 10){ +		digits = 0; +		accept(); +	} +} + +/** + * remove_digit: + * Remove one digit from the selected cpr + * Used when the user pushes backspace in + * the inputwindow + */ +void CPRQueryDialog::remove_digit()  +{ +  int temp; +  temp = strlen(cpr); +  if (temp == 7) /* Remove two characters due to the hyphen */ +    strcpy(cpr+temp-2, "\0"); +  else if ((temp >0) && (temp <=11)) +    strcpy(cpr+temp-1, "\0"); +  lbl_cpr->setText(cpr); +} + +/** + * remove_all: + * Clear the selected cpr  + */ +void CPRQueryDialog::remove_all()  +{ +  strcpy(cpr, ""); +  lbl_cpr->setText(cpr); +} + +/** + * insert_digit: + * Respond to what the user types in the inputWindow  + */ +void CPRQueryDialog::insert_digit(int value) +{ +  char temp[2]; +  switch(strlen(cpr)) { +  case 5: // Automaticaly add a hyphen after the sixth digit +    sprintf(temp, "%d-", value); +    strcat(cpr, temp); +    lbl_cpr->setText(cpr); +    break; +  case 10: +    sprintf(temp, "%d", value); +    strcat(cpr, temp); +    lbl_cpr->setText(cpr); +    verifycpr(cpr); +    break; +  default: +    sprintf(temp, "%d", value); +    strcat(cpr, temp); +    lbl_cpr->setText(cpr); +    break; +  } +} + +/** + * verifycpr: + * Test a cpr via test_cpr(). + * If cpr is invalid, then ask user what + * to do via MessageBox + */ +void CPRQueryDialog::verifycpr(char *cpr)  +{ +  strncpy(internalCpr, cpr, 6); +  strncpy(internalCpr+6, cpr+7, 4); +  internalCpr[10] = 0; +   +  if (!(test_cpr(internalCpr))) { +    MessageBox ccw(this, CONFIRM_INVALID_CPR_TITLE, CONFIRM_INVALID_CPR, TYPE_YES_NO_CANCEL); +    switch(ccw.exec()) { +    case MSG_CANCEL: +      bedit_clicked(); +      break; +    case MSG_NO: +      bcancel_clicked(); +      break; +    case MSG_YES: +      // Overwrite name from previous cpr. +      lbl_name->setText(NAME_NOT_AVAILABLE); +      accept(); +      break; +    } +  } else { +    cprSocket->connectToHost(CPR_HOST->c_str(), CPR_PORT); +    timer->start(CPR_TIMEOUT); +    //    accept(); +  } +} + + +/* Clears all data - alerts user if measurements are not stored */ +void CPRQueryDialog::bcancel_clicked() +{ +  cpr[0]= '\0'; +  lbl_cpr->setText("Indtast CPR"); +  lbl_name->setText(""); +} + +/* This is used when the user enters a cpr that is not valid and wishes to edit + * the cpr. + */ +void CPRQueryDialog::bedit_clicked()  +{ +  cpr[10]= '\0'; +  lbl_cpr->setText(cpr); +  lbl_name->setText(""); +} + + +/** + * test_cpr: + * Checks that a cpr i valid via a modulo 11 test  + */ +int CPRQueryDialog::test_cpr(const char *s) +{ +  int sum = 0; +  int ctl; +  const char *cptr; +   +  // Is the string to short to be a cpr? +  if(strlen(s) != 10) return 0; +   +  // Are all characters digits? +  for(cptr = s; *cptr; cptr++) if(!isdigit(*cptr)) return 0; + +  // Calculate modulo 11 checksum +  sum += (s[0] - '0') * 4; +  sum += (s[1] - '0') * 3; +  sum += (s[2] - '0') * 2; +  sum += (s[3] - '0') * 7; +  sum += (s[4] - '0') * 6; +  sum += (s[5] - '0') * 5; +  sum += (s[6] - '0') * 4; +  sum += (s[7] - '0') * 3; +  sum += (s[8] - '0') * 2; +  ctl = 11 - (sum % 11); + +  // Is the checksum correct? +  if(ctl == 11) ctl = 0; +  return s[9] - '0' == ctl; +} + +/** + * cprSocket_error + * Called if an error occurres in the corsocket connection. + * Writes out the appropriate error message. + */ +void CPRQueryDialog::cprSocket_error(int errnum) +{ +  QString msg = QString("cprSocket encountered an error: "); +  timer->stop(); +   +  lbl_name->setText(NAME_NOT_AVAILABLE); + +  // Print error message +  switch(errnum) { +  case QSocket::ErrConnectionRefused: // if the connection was refused +    msg.append("ErrConnectionRefused"); +    break; +  case QSocket::ErrHostNotFound: // if the host was not found +    msg.append("ErrHostNotFound"); +    break; +  case QSocket::ErrSocketRead: // if a read from the socket failed  +    msg.append("ErrSocketRead"); +    break; +  } + +  if(statusbar) statusbar->message(msg, 5000); +  MessageBox(this, "Fejl", msg, TYPE_OK, ICON_ERROR).exec(); +  //info->error(msg.c_str()); +  accept(); +} + +/** + * cprSocket_readyRead: + * Uses a patients cpr to look up his or hers name + * via the departments cpr-server. + * This is called by the cprSocket when the socket is ready + */ +void CPRQueryDialog::cprSocket_readyRead()  +{ +  QString name; +  QString firstname; +  QString lastname; +  int timeout = 0; + +  if (!cprSocket->canReadLine()) return; + +  QString msg = QString("Recieving name from cpr database..."); +  if(statusbar) statusbar->message(msg, 5000); +  timer->stop(); + +  while(cprSocket->canReadLine()) { +    QString s = cprSocket->readLine(); +    if (s.startsWith("0001")) { +      name.append(s.right(s.length()-4)); +      lastname.append(s.right(s.length()-4)); +      name.setLength(name.length()-1); +      if (name.length()) name += QString(", "); +    } +    if (s.startsWith("0002")) { +      name.append(s.right(s.length()-4)); +      firstname.append(s.right(s.length()-4)); +      name.setLength(name.length()-1); +      cprSocket->close(); +      lbl_name->setText(name); +      accept(); +      return; +    } +    if (timeout>1000) { +      lbl_name->setText(NAME_NOT_AVAILABLE); +      MessageBox(this, NAME_NOT_AVAILABLE_TITLE, NAME_NOT_AVAILABLE, TYPE_OK, ICON_ERROR).exec(); +      accept(); +      return; +    } +    timeout++; +  } +   +  accept(); +} + + +/** + * cprSocket_connected: + * Writes the selected cpr to the cpr-server + * when the cprSocket is connected. + */ +void CPRQueryDialog::cprSocket_connected()  +{	 +  QString msg = QString("Connected to cpr database, sending cpr number..."); +  if(statusbar) statusbar->message(msg, 5000); +  timer->stop(); + +  cprSocket->writeBlock(internalCpr, 10); +  cprSocket->writeBlock("\n", 1); +} + +/** + * cprSocket_timeout: + * Called when the connection has not emitted a signal in CPR_TIMEOUT miliseconds. + */ +void CPRQueryDialog::cprSocket_timeout() +{ +  QString msg = QString("cprSocket timed out doing: "); +  timer->stop(); + +  lbl_name->setText(NAME_NOT_AVAILABLE); + + +  // Print connection status +  switch(cprSocket->state()) { +  case QSocket::Idle:       // if there is no connection +    msg.append("Idle"); +    break; +  case QSocket::HostLookup: // during a DNS lookup +    msg.append("HostLookup"); +    break; +  case QSocket::Connecting: // during TCP connection establishment +    msg.append("Connecting"); +    break; +  case QSocket::Connected:  // when there is an operational connection +    msg.append("Conected"); +    break; +  case QSocket::Closing:    // if the socket is closing down, but is not yet closed. +    msg.append("Closing"); +    break; +  } +   +  if(statusbar) statusbar->message(msg, 5000); +  MessageBox(this, "Fejl", msg, TYPE_OK, ICON_ERROR).exec(); +  accept(); +} + +#endif /* USE_GUI */ diff --git a/client/cprquerydialog.h b/client/cprquerydialog.h new file mode 100644 index 0000000..85b2659 --- /dev/null +++ b/client/cprquerydialog.h @@ -0,0 +1,170 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            cprquerydialog.h + * + *  Sat Feb 19 17:05:42 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __MIAV_CPRQUERYDIALOG_H__ +#define __MIAV_CPRQUERYDIALOG_H__ + +/** + * Text + */ +#define NAME_NOT_AVAILABLE_TITLE "Databasefejl" +#define NAME_NOT_AVAILABLE "Kunne ikke slĺ navn op i cpr-database." + +#define CONFIRM_INVALID_CPR_TITLE "Bekrćft" +#define CONFIRM_INVALID_CPR "Ugyldigt CPR nummer, brug det alligevel?" + + +/**  + * Images + */ +#define PIXMAP_BACKSPACE     PIXMAPS"/backspace.png" + + +/**  + * Includes + */ +#include <qdialog.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qfont.h> + +#include <qwidget.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qdialog.h> +#include <qlabel.h> +#include <qpixmap.h> + +#include <qsocket.h> +#include <qtextedit.h> +#include <qstring.h> +#include <qwidget.h> + +#include <qevent.h> + +#include <qpushbutton.h> + +#include <qwidget.h> +#include <qlayout.h> +#include <qdialog.h> + +#include <string> +using namespace std; + +#include <qdialog.h> +#include <qlabel.h> +#include <qsocket.h> +#include <qtimer.h> +#include <qstatusbar.h> + +#include "messagebox.h" + +#include "cprlisten.h" + +#include "info.h" + +class CPRQueryDialog : public QDialog { +  Q_OBJECT +public: +  CPRQueryDialog(Info *info, +                 QLabel *lcpr,  +                 QLabel *lname,  +                 QWidget * parent = 0,  +                 const char * name = 0, +                 QStatusBar *status = NULL); +  ~CPRQueryDialog(); +   +public slots: +  void bcancel_clicked(); +  void bedit_clicked(); +  void remove_digit(); +  void remove_all(); +  void insert_digit(int value);	 +  void cprSocket_readyRead(); +  void cprSocket_connected(); +  void cprSocket_error(int errnum); +  void cprSocket_timeout(); +  void listen_timeout(); + + +private: +  Info *info; + +  CPRListen *listen; +  QTimer *listen_timer; + +  QStatusBar *statusbar; + +  QLabel *lbl_cpr; +  QLabel *lbl_name; + +  QSocket *cprSocket;	 +  char cpr[12]; +  char internalCpr[11]; +   +  void verifycpr(char *cpr); +  //  void run(int pos); +  int test_cpr(const char *s); +   +  /*Configuration*/ +  string *CPR_HOST; +  int CPR_PORT; +  int CPR_TIMEOUT; + +signals: +  void bbs_clicked(); +  void bca_clicked(); +  void number_clicked(int); + +public slots: +  void b_1_clicked(); +  void b_2_clicked(); +  void b_3_clicked(); +  void b_4_clicked(); +  void b_5_clicked(); +  void b_6_clicked(); +  void b_7_clicked(); +  void b_8_clicked(); +  void b_9_clicked(); +  void b_0_clicked(); +  void b_b_clicked(); +  void b_c_clicked(); + +private: +  void b_clicked(int value); +  QPushButton *createButton(QWidget *parent, const char *text, int value); +  int digits; + +  QTimer *timer; +}; + +#endif /* USE_GUI */ + +#endif/*__MIAV_CPRQUERYDIALOG_H__*/ diff --git a/client/debug.h b/client/debug.h new file mode 100644 index 0000000..48c0830 --- /dev/null +++ b/client/debug.h @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            debug.h + * + *  Tue Apr 12 14:34:20 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifndef __MIAV_DEBUG_H__ +#define __MIAV_DEBUG_H__ + +//#define DEBUG_ALLOC + +#ifdef DEBUG_ALLOC +typedef struct _A_{ +  struct _A_* prev; +  struct _A_* next; +  char name[32]; +  void *addr; +} __debug__; + +__debug__ *debug_first = NULL; + +inline void debugAlloc(void *p, char* name) +{ +  __debug__ *d = debug_first; +   +  fprintf(stderr, "Adding %d - %s\n", p, name); + +  debug_first = (__debug__*)malloc(sizeof(__debug__)); +  debug_first->prev = NULL; +  debug_first->next = d; +  if(d) d->prev = debug_first; +  debug_first->addr = p; +  strcpy(debug_first->name, name); +} + +inline void debugFree(void *p) +{ +  __debug__ *d = debug_first; + +  while(d && d->addr != p) { +    d = d->next; +  } +     +  if(!d) { +    fprintf(stderr, "ERROR: memory address not found %d - perhaps already freed!\n", p); +    exit(1); +  } + +  fprintf(stderr, "Removing %d - %s\n", p, d->name); +  __debug__ *next = d->next; +  __debug__ *prev = d->prev; +  if(prev) prev->next = d->next; +  if(next) next->prev = d->prev; +  if(debug_first == d) debug_first = next; +  free(d); +} + +inline void debugPrint() +{ +  __debug__ *d = debug_first; +   +  fprintf(stderr, "Alloc List:\n"); + +  while(d) { +    fprintf(stderr, "\t[%d] %s\n", d->addr, d->name); +    d = d->next; +  } +} + +#define FREE(x) debugFree(x)  +#define ALLOC(x, y) debugAlloc(x, y) +#define PRINT() debugPrint() + +#else/*DEBUG_ALLOC*/ + +#define FREE(x) {} +#define ALLOC(x, y) {} +#define PRINT() {} + +#endif/*DEBUG_ALLOC*/ + +#endif/*__MIAV_DEBUG_H__*/ diff --git a/client/decoder.cc b/client/decoder.cc new file mode 100644 index 0000000..0d56aca --- /dev/null +++ b/client/decoder.cc @@ -0,0 +1,286 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            decoder.cc + * + *  Sat Feb 19 17:05:43 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  B. Stultiens + * Copyright (C) 2004  Koen Otter and Glenn van der Meyden + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "frame_stream.h" + +#include "miav_config.h" + +#include <time.h> + +// Use libdv +#include <libdv/dv.h> +#include <libdv/dv_types.h> + +#include <SDL/SDL.h> + +#include "dv.h" +#include "dvfile.h" +#include "dv1394.h" + +#include "decoder.h" +#include "debug.h" + +Decoder::Decoder(Info *ginfo, +                 sem_t *gencode_sem, +                 sem_t *gplayer_sem, +                 Queue<Frame> *gencode_queue, +                 Queue<Frame> *gplayer_queue, +                 pthread_mutex_t *gmutex, +                 volatile int *grunning) +{ +  info = ginfo; + +  encode_sem = gencode_sem; +  player_sem = gplayer_sem; +  encode_queue = gencode_queue; +  player_queue = gplayer_queue; +  mutex = gmutex; +  running = grunning; + +  b_shoot = false; +  b_freeze = false; +  b_record = false; // Initially no recording is done. + +  pthread_mutex_init (&shot_mutex, NULL); +  shot = NULL; + +  mute = false; +} + +Decoder::~Decoder() +{ +  pthread_mutex_destroy(&shot_mutex); +} + +void Decoder::decode() +{ +  frame_stream *dvstream; + +  bool local_shoot; +  int local_freeze; +  bool local_record = false; +  bool old_record; + +  bool skip_frames = config->readInt("player_skip_frames"); + +  dv1394 dv1394_stream = dv1394(info); // Use default port and channel. +  dvfile dvfile_stream = dvfile(info); +  if(dv1394_stream.connect()) {  +    // Use the dv1394 stream for input. +    dvstream = &dv1394_stream; +  } else { +    // Use the fallback dv filereader for input. +    dvstream = &dvfile_stream; +  } + +  while(*running) { +    uint8_t *ptr; +    SDL_Event user_event; +     +    // Read a dvframe +    ptr = dvstream->readFrame(); +    if(!ptr) return; // No frame read. (Due to dv read error) + +    old_record = local_record; +    local_shoot = b_shoot; +    b_shoot = false; +    local_freeze = b_freeze; +    b_freeze = false; +    local_record = b_record; + +    if(local_shoot) { +      pthread_mutex_lock(&shot_mutex); +      if(!shot) shot = new Frame(ptr, DVPACKAGE_SIZE); +      pthread_mutex_unlock(&shot_mutex); +    } +     +    if(local_freeze == 1) { +      pthread_mutex_lock(&shot_mutex); +      if(shot) delete shot; +      shot = new Frame(ptr, DVPACKAGE_SIZE); +      pthread_mutex_unlock(&shot_mutex); +    } + +    static int showframe = 1; +    if(skip_frames != 0) showframe = 1 - showframe; +    if(showframe) { +      Frame *pframe = new Frame(ptr, DVPACKAGE_SIZE); + +      pframe->shoot = local_shoot; +      pframe->freeze = local_freeze; +      pframe->record = local_record; + +      player_queue->push(pframe); +     +      // Create and send SDL event. +      user_event.type = SDL_USEREVENT; +      user_event.user.code = 0; +      user_event.user.data1 = NULL; +      user_event.user.data2 = NULL; +      SDL_PushEvent(&user_event); +    } + +    if(local_record | (local_record != old_record) | local_shoot | local_freeze) { +      Frame *eframe = new Frame(NULL, 0); +      eframe->data = ptr; +      eframe->size = DVPACKAGE_SIZE; + +      eframe->shoot = local_shoot; +      eframe->freeze = local_freeze; +      eframe->record = local_record; +      eframe->mute = mute; +     +      encode_queue->push(eframe); +       +      sem_post(encode_sem); +    } else { +      free(ptr); +    } +  } + +  // Kick the others so they wake up with empty queues +  sem_post(encode_sem); +} + +void Decoder::thread_main() { +  decode(); +  fprintf(stderr, "Decoder thread stopped.\n"); fflush(stderr); +} + +/* + * Set freeze bit on current frame. + */ +void Decoder::freeze() +{   +  b_freeze = 1; +} + +/* + * Remove frozen frame. + */ +void Decoder::unfreeze() +{   +  b_freeze = -1; + +  pthread_mutex_lock(&shot_mutex); +  delete shot; +  shot = NULL; +  pthread_mutex_unlock(&shot_mutex); +} + +/* + * Set shoot bit on current frame. + */ +void Decoder::shoot(unsigned char *rgb) +{ +  struct timespec ts; + +  b_shoot = true; + +  // Wait for shot to be taken +  while(1) { +    pthread_mutex_lock(&shot_mutex); +    if(shot) { +      getScreenshot(shot, rgb); +      delete shot; +      shot = NULL; +      pthread_mutex_unlock(&shot_mutex); +      return; +    } +    pthread_mutex_unlock(&shot_mutex); + +    ts.tv_sec = 0; +    ts.tv_nsec = 100000000L;	// 100ms +    nanosleep(&ts, NULL); +  } +} + +/* + * Set the record bit to true in all following frames. + */ +void Decoder::start() +{ +  b_record = true; +} + +/* + * Set the record bit to false in all following frames. + */ +void Decoder::stop(n_savestate save) +{ +  b_record = false; +} + +void Decoder::getScreenshot(Frame *frame, unsigned char *rgb) +{ +  unsigned char *pixels[3]; +  int pitches[3]; + +  pixels[ 0 ] = rgb; +  pixels[ 1 ] = NULL; +  pixels[ 2 ] = NULL; + +  pitches[ 0 ] = 720 * 4; +  pitches[ 1 ] = 0; +  pitches[ 2 ] = 0; +   +	dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); +  decoder->quality = DV_QUALITY_BEST; + +  dv_parse_header(decoder, frame->data); +   +  decoder->system = e_dv_system_625_50;  // PAL lines, PAL framerate +  decoder->sampling = e_dv_sample_422;  // 4 bytes y, 2 bytes u, 2 bytes v +  decoder->std = e_dv_std_iec_61834; +  decoder->num_dif_seqs = 12; +   +  // libdv img decode to rgb +  dv_decode_full_frame(decoder, +                       frame->data, +                       e_dv_color_bgr0, +                       pixels, +                       pitches); +   +  dv_decoder_free(decoder); +} + +void Decoder::setMute(bool m) +{ +  mute = m; +} + +#endif /*USE_GUI*/ diff --git a/client/decoder.h b/client/decoder.h new file mode 100644 index 0000000..20878c7 --- /dev/null +++ b/client/decoder.h @@ -0,0 +1,99 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            decoder.h + * + *  Sat Feb 19 17:05:42 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  B. Stultiens + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __RTVIDEOREC_DECODER_H +#define __RTVIDEOREC_DECODER_H + +#include "info.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "queue.h" +#include "encoder.h" +#include "player.h" + +#include "thread.h" +#include "frame.h" + +class Decoder : public Thread { +public: +  Decoder(Info *ginfo, +          sem_t *gencode_sem, +          sem_t *gplayer_sem, +          Queue<Frame> *gencode_queue, +          Queue<Frame> *gplayer_queue, +          pthread_mutex_t *gmutex, +          volatile int *grunning); +  ~Decoder(); +  void thread_main(); + +  void freeze(); +  void unfreeze(); +  void shoot(unsigned char *rgb); +  void start(); +  void stop(n_savestate save); +  void setMute(bool mute); + +private: +  volatile bool mute; + +  void getScreenshot(Frame *frame, unsigned char *rgb); + +  pthread_mutex_t shot_mutex; +  Frame* shot; + +  volatile int b_freeze; +  volatile bool b_shoot; +  volatile bool b_record; + +  Info *info; +  //  AVCodecContext dvcodec; + +  sem_t *encode_sem; +  sem_t *player_sem; +  Queue<Frame> *encode_queue; +  Queue<Frame> *player_queue; +  pthread_mutex_t *mutex; +  volatile int *running; + +  void decode(); +}; + +#endif/* __RTVIDEOREC_DECODER_H*/ + +#endif/*USE_GUI*/ diff --git a/client/dv.h b/client/dv.h new file mode 100644 index 0000000..e346d03 --- /dev/null +++ b/client/dv.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            dv.h + * + *  Thu Apr 14 19:29:55 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifndef __MIAV_DV_H__ +#define __MIAV_DV_H__ + +#define DVPACKAGE_SIZE 144000 + +#endif/*__MIAV_DV_H__*/ diff --git a/client/dv1394.cc b/client/dv1394.cc new file mode 100644 index 0000000..270da2e --- /dev/null +++ b/client/dv1394.cc @@ -0,0 +1,175 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            dv1394.cc + * + *  Tue Apr 19 12:10:34 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#include "dv1394.h" + +#ifdef USE_GUI + +#include "dv.h" + + +#include <stdlib.h> +#include <memory.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> + + + +/** + * Callback function for the firewire interface. + */ +static int raw_reader( raw1394handle_t handle, int channel, size_t length, quadlet_t *data ) +{ +	static char *framedata = NULL; + +  // Only process packets with reasonable length. +	if ( length > 16 ) +	{ +		unsigned char * p = ( unsigned char* ) & data[ 3 ]; +		int section_type = p[ 0 ] >> 5;           // section type is in bits 5 - 7 +		int dif_sequence = p[ 1 ] >> 4;           // dif sequence number is in bits 4 - 7 +		int dif_block = p[ 2 ]; + +		if ( section_type == 0 && dif_sequence == 0 ) +		{ +			if ( framedata != NULL ) +			{ +				raw1394_set_userdata(handle, (void *)framedata); +				framedata = NULL; +			} +		} + +		if(!framedata) +		{ +			framedata = (char *)malloc(DVPACKAGE_SIZE); // dvframe.h +			if(!framedata) +			{ +				// We're fucked +        fprintf(stderr, "Framedata allocation error: %s.\n", strerror( errno ) ); fflush(stderr); +				exit(1); +			} +		} + +		switch ( section_type ) +		{ +		case 0:    // 1 Header block +			// p[3] |= 0x80; // hack to force PAL data +			memcpy( framedata + dif_sequence * 150 * 80, p, 480 ); +			break; + +		case 1:    // 2 Subcode blocks +			memcpy( framedata + dif_sequence * 150 * 80 + ( 1 + dif_block ) * 80, p, 480 ); +			break; + +		case 2:    // 3 VAUX blocks +			memcpy( framedata + dif_sequence * 150 * 80 + ( 3 + dif_block ) * 80, p, 480 ); +			break; + +		case 3:    // 9 Audio blocks interleaved with video +			memcpy( framedata + dif_sequence * 150 * 80 + ( 6 + dif_block * 16 ) * 80, p, 480 ); +			break; + +		case 4:    // 135 Video blocks interleaved with audio +			memcpy( framedata + dif_sequence * 150 * 80 + ( 7 + ( dif_block / 15 ) + dif_block ) * 80, p, 480 ); +			break; + +		default:   // we can't handle any other data +			break; +		} +	} +	return 0; +} + +dv1394::dv1394(Info *i, int p, int c) +{ +  info = i; +  port = p; +  channel = c; +} + +dv1394::~dv1394() +{ +  // Close firewire connection. +  if(handle) raw1394_destroy_handle(handle); +} + +bool dv1394::connect() +{ +	int n_ports; +	struct raw1394_portinfo pinf[ 16 ]; + +  // Get handle to firewire channels +	handle = raw1394_new_handle(); +	if(!handle) { +    info->error("raw1394 - failed to get handle: %s.", strerror( errno ) ); +    return false; +	} + +  // how many adapters are hooked in? +	if((n_ports = raw1394_get_port_info(handle, pinf, 16)) < 0 ) { +    info->error("raw1394 - failed to get port info: %s.", strerror( errno ) ); +    raw1394_destroy_handle(handle); +    handle = NULL; +    return false; +	} + +	// Tell raw1394 which host adapter to use +	if(raw1394_set_port(handle, port) < 0 ) { +    info->error("raw1394 - failed to set port: %s.", strerror( errno ) ); +    raw1394_destroy_handle(handle); +    handle = NULL; +    return false; +	} + +	raw1394_set_iso_handler( handle, channel, raw_reader); +	raw1394_set_userdata( handle, ( void* ) NULL); +  raw1394_start_iso_rcv( handle, channel); +   +  return true; +} + +unsigned char *dv1394::readFrame() +{ +  // Firewire port not correctly opened. +  if(!handle) return NULL; + +  unsigned char *ptr; +  while(1) { +    raw1394_loop_iterate(handle); +    ptr = (unsigned char *)raw1394_get_userdata(handle); +    if(ptr) { +      raw1394_set_userdata(handle, NULL); +      break; +    } +  } +  return ptr; +} + +#endif/*USE_GUI*/ diff --git a/client/dv1394.h b/client/dv1394.h new file mode 100644 index 0000000..7cea9d0 --- /dev/null +++ b/client/dv1394.h @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            dv1394.h + * + *  Tue Apr 19 12:10:34 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifndef __MIAV_DV1394_H__ +#define __MIAV_DV1394_H__ + +#ifdef USE_GUI + +#include "frame_stream.h" +#include <libraw1394/raw1394.h> + +#include "info.h" + +class dv1394 : public frame_stream { +public: +  dv1394(Info* info, int port = 0, int channel = 63); // 63 is default channel... sucks. +  ~dv1394(); + +  bool connect(); + +  unsigned char *readFrame(); + +private: +  raw1394handle_t handle; +  Info *info; +  int port; +  int channel; +}; + +#endif/*__MIAV_DV1394_H__*/ +#endif/*USE_GUI*/ diff --git a/client/encoder.cc b/client/encoder.cc new file mode 100644 index 0000000..e7b79bf --- /dev/null +++ b/client/encoder.cc @@ -0,0 +1,273 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            encoder.cc + * + *  Tue Apr 19 12:10:34 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  B. Stultiens + * Copyright (C) 2004  Koen Otter and Glenn van der Meyden + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "util.h" +#include "encoder.h" + +Encoder::Encoder(Info *ginfo, +                 const char *gip, +                 const int gport, +                 sem_t	*gsem, +                 Queue<Frame> *gqueue, +                 pthread_mutex_t *gmutex, +                 volatile int *grunning) +{ +  info = ginfo; + +  strcpy(ip, gip); +  port = gport; +  memset(cpr, 0, sizeof(cpr)); + +  sem = gsem; +  queue = gqueue; +  mutex = gmutex; +  running = grunning; + +  //  record = 0; + + 	sem_init(&record_sem, 0, 0); + +  s = NULL; +  n = NULL; + +  frozen = false; + +  savestate_sent = false; +  savestate = NO_CHANGE; + +  //  shoot_request = 0; +  //  shoot_value = 0; +  //  freeze_request = 0; +  //  freeze_value = 0; +} + + +Encoder::~Encoder() +{ +  // If a hanging connection exists, we better close it. +  /* // Already deleted in thread_main +  if(s) { +    if(n) delete n; +    delete s; +    s = NULL; +    n = NULL; +  } +  */ +} + + +void Encoder::encode() +{  +  Frame *frame; + +  while(*running) { +    sem_wait(sem); + +    frame = queue->pop(); +     +    if(frame) { +      if(frame->freeze == 1) frozen = true; +      if(frame->freeze == -1) frozen = false; +      if(frame->shoot) frozen = false; + +      if(frame->record ||  +         (frame->freeze == 1) ||  +         frame->shoot) { + +        // If no connection is present, make a new one +        if(!s) { +          s = new Socket(port, info); +          s->sconnect(ip); +          n = new Network(s, info); +        } + +        n_header h; +       +        if(savestate != NO_CHANGE) savestate_sent = true; + +        h.header_type = DATA_HEADER; +        sprintf(h.header.h_data.cpr, cpr); +        h.header.h_data.freeze = frame->freeze; +        h.header.h_data.snapshot = frame->shoot; +        h.header.h_data.record = frame->record; +        h.header.h_data.savestate = savestate;//NO_CHANGE; +        h.header.h_data.mute = frame->mute; + +        savestate = NO_CHANGE; // only transmit once! +         +        //        if(freeze_request != freeze_value) freeze_value = freeze_request; +        //        if(shoot_request != shoot_value) shoot_value = shoot_request; +         +        n->sendPackage(&h, frame->data, frame->size); +      } else { +        // When frozen we need to preserve the connection in order to +        // remember the frozen frame on the server side. +        if(!frozen) { +          // No data is to be sent, if we have a connection, destroy it. +          if(s) { +            if(n) delete n; +            delete s; +            s = NULL; +            n = NULL; +          } +        } +      } + +      if(frame->shoot && !frozen && !frame->record) { +        // FIXME: This is ugly! +        // Bugfix... connection not cleared, when an 'unfrozen' snapshot is taken,  +        // and no recording is done. +        if(s) { +          if(n) delete n; +          delete s; +          s = NULL; +          n = NULL; +        } +      } + +      if(frame) delete frame; +    } +  } +} + + +void Encoder::setCpr(char *newcpr) +{ +  strcpy(cpr, newcpr); +} + + +void Encoder::freeze() +{  +  /*  +  if(!s) { +    s = new Socket(port, errobj); +    s->sconnect(ip); +    n = new Network(s, errobj); +  } +  */ +  //  if(!errobj->hasError()) freeze_request = 1 - freeze_request; +} + + +/* + * shoot + * Set the shoot bit in the network header on the current frame. + * return the decodet (rgba) version af that frame, for thumbnail show. + */ +void Encoder::shoot() +{ +  /* +  if(!s) { +    s = new Socket(port, errobj); +    s->sconnect(ip); +    n = new Network(s, errobj); +  } +  */ +  //  if(!errobj->hasError()) shoot_request = 1 - shoot_request; +  //  getScreenshot(rgb); +} + + +void Encoder::thread_main() +{ +  encode(); +  if(s) { +    if(n) delete n; +    delete s; +    s = NULL; +    n = NULL; +  } +  fprintf(stderr, "Encoder thread stopped.\n"); fflush(stderr); +} + + +void Encoder::start() +{ +  savestate = NO_CHANGE; +  savestate_sent = false; +  /* +  if(!s) { +    s = new Socket(port, errobj); +    s->sconnect(ip); +    n = new Network(s, errobj); +  } +  */ +  //  if(!errobj->hasError()) record = 1; +} + + +void Encoder::stop(n_savestate save) +{ +  savestate = save; +  // Don't return until we are sure the savestate has been sent. +  while(savestate_sent == false) { +    // Just wait a while (in a while!) +    sleep_0_2_frame(); +  } +/* +  struct timespec ts; +  // TODO: set save state in package header. + +  // Lock the queue and wait until all elements are sent on the network. +  queue->lock(); +  fprintf(stderr, "Emptying queue"); fflush(stderr); +  while(queue->peek()) { +    // Remove any late buffer +    // We don't care, the encoder finishes them all +    ts.tv_sec = 0; +    ts.tv_nsec = 500000000L;	// 100ms +    fprintf(stderr, "."); fflush(stderr); +    nanosleep(&ts, NULL); +  } +  fprintf(stderr, "done!\n"); fflush(stderr); + +  record = 0; + +  queue->unlock(); +*/ +/* +  if(s) { +    if(n) delete n; +    delete s; +    s = NULL; +    n = NULL; +  } +*/ +} + +#endif /*USE_GUI*/ diff --git a/client/encoder.h b/client/encoder.h new file mode 100644 index 0000000..0fada07 --- /dev/null +++ b/client/encoder.h @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            encoder.h + * + *  Thu Apr 14 19:29:55 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  B. Stultiens + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __RTVIDEOREC_ENCODER_H +#define __RTVIDEOREC_ENCODER_H + +#include "thread.h" + +#include "info.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +//#include <avformat.h> + +#include "miav.h" +#include "util.h" +#include "package.h" +#include "frame.h" +#include "queue.h" + +// FIXME: One size fits all... +#define VIDEO_BUFFER_SIZE	(1024*1024) + + +/** + * This class contains code for sending the video stream and the snapshots + * over the network, to the MIaV server. + */ +class Encoder : public Thread { +public: +  Encoder(Info* ginfo, +          const char *gip, +          const int gport, +          sem_t	*gsem, +          Queue<Frame> *gqueue, +          pthread_mutex_t *gmutex, +          volatile int *grunning); +  ~Encoder(); +   +  void setCpr(char *newcpr); + +  void start(); +  void stop(n_savestate save); + +  void freeze(); +  void shoot(); + +  void thread_main(); + +  //  AVFormatContext *fc; +  sem_t	*sem; +  Queue<Frame> *queue; +  pthread_mutex_t *mutex; +  volatile int *running; + +private: +  Info *info; + +  int port; +  char ip[32]; +  char cpr[32]; + +  bool frozen; + +  //  volatile int record; + +  //  volatile int shoot_request; +  //  int shoot_value; +  //  volatile int freeze_request; +  //  int freeze_value; + +  volatile bool savestate_sent; +  volatile n_savestate savestate; +   +  sem_t	record_sem; +  void encode(); + +  Socket *s; +  Network *n; +}; + +#endif + +#endif /*USE_GUI*/ diff --git a/client/historywidget.cc b/client/historywidget.cc new file mode 100644 index 0000000..bdeb880 --- /dev/null +++ b/client/historywidget.cc @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            historywidget.cc + * + *  Wed Jul 27 14:00:37 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of MIaV. + * + *  MIaV 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. + * + *  MIaV 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 MIaV; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI +#include "historywidget.h" + +#include "miav_config.h" + +HistoryWidget::HistoryWidget(QWidget *p) : QLabel(p) +{ +  parent = p; +  image = NULL; +} + +HistoryWidget::~HistoryWidget() +{ +  if(image) delete image; +} + +void HistoryWidget::set_image(QImage *i) +{ +  if(image) delete image; + +  image = new QImage(*i); + +  QImage resized = image->smoothScale(width(), height()); +  setPixmap(resized); +} + +QImage * HistoryWidget::get_image() +{ +  return image; +} + +static HistoryWidget *fs = NULL; + +void HistoryWidget::mouseReleaseEvent(QMouseEvent *event) +{ +  if(!parent) {    // We are a fullscreen window +    destroy(); +  } else {         // We are a nested window +    // Delete old instances before going fullscreen. +    if(fs) delete fs; +     +    fs = new HistoryWidget(NULL); +    fs->showFullScreen(); +    fs->setFixedWidth(config->readInt("pixel_width")); +    fs->setFixedHeight(config->readInt("pixel_height")); +    fs->set_image(image); +  } +} + +#endif/*USE_GUI*/ diff --git a/client/historywidget.h b/client/historywidget.h new file mode 100644 index 0000000..d464d59 --- /dev/null +++ b/client/historywidget.h @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            historywidget.h + * + *  Wed Jul 27 14:00:37 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of MIaV. + * + *  MIaV 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. + * + *  MIaV 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 MIaV; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +#ifndef __MIAV_HISTORYWIDGET_H__ +#define __MIAV_HISTORYWIDGET_H__ + +#include <qlabel.h> +#include <qimage.h> + +class HistoryWidget : public QLabel { +Q_OBJECT +public: +  HistoryWidget(QWidget *parent); +  ~HistoryWidget(); + +  void set_image(QImage *image); +  QImage *get_image(); + +  void mouseReleaseEvent(QMouseEvent *event); + +private: +  QImage *image; +  QWidget *parent; +}; + +#endif/*__MIAV_HISTORYWIDGET_H__*/ +#endif/*USE_GUI*/ diff --git a/client/info_gui.cc b/client/info_gui.cc new file mode 100644 index 0000000..aa831b6 --- /dev/null +++ b/client/info_gui.cc @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            info_gui.cc + * + *  Tue May  3 09:34:59 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "info_gui.h" + +#include <stdio.h> +#include <stdarg.h> + +#include <time.h> + +bool InfoEventHandler::eventFilter( QObject *o, QEvent *e ) +{ +  if ( e->type() == TYPE_SHOW_MESSAGEBOX ) { +    //    fprintf(stderr, "Custom event!\n"); fflush(stderr); +    MessageBox *msgbox = ((ShowMessageEvent*)e)->messagebox(); +    msgbox->exec(); +    delete msgbox; +    return TRUE; // eat event +  } else { +    // standard event processing +    return FALSE; +  } +} + +InfoGui::InfoGui(QApplication *a, QWidget *p, MiavConfig *c): Info() +{ +  this->config = c; +  log_filename = *(this->config->readString("client_log_file")); + +  qapp = a; +  parent = p; + +  pthread_mutex_init (&mutex, NULL); +} + +InfoGui::~InfoGui() +{ +  pthread_mutex_destroy(&mutex); +} + +void InfoGui::setParent(QWidget *p) +{ +  parent = p; +} + +void InfoGui::showmsg(char *msg, char *title, msg_icon icon) +{ +  pthread_mutex_lock(&mutex); +  // Beginning of safezone + +  fprintf(stderr, "%s: %s\n", title, msg); fflush(stderr); + +  while( !parent ) { +    struct timespec ts; + +    ts.tv_sec = 0; +    ts.tv_nsec = 200000000L;	// 200ms +    nanosleep(&ts, NULL); +  } + +  MessageBox *msgbox = new MessageBox(parent,  +                                      title, +                                      msg,  +                                      TYPE_OK,  +                                      icon); + +  ShowMessageEvent *event = new ShowMessageEvent( msgbox ); +   +  qapp->postEvent(parent, event); + +  // End of safezone +  pthread_mutex_unlock(&mutex); +} + +void InfoGui::error(char *fmt, ...) +{ +  char buf[1024]; + +	va_list argp; +	va_start(argp, fmt); +	vsprintf(buf, fmt, argp); +	va_end(argp); + +  showmsg(buf, TXT_ERROR_TITLE, ICON_ERROR); + +  log("Error: %s", buf); +} + +void InfoGui::warn(char *fmt, ...) +{ +  char buf[1024]; + +	va_list argp; +	va_start(argp, fmt); +	vsprintf(buf, fmt, argp); +	va_end(argp); + +  showmsg(buf, TXT_WARNING_TITLE, ICON_WARNING); + +  log("Warning: %s", buf); +} + +void InfoGui::info(char *fmt, ...) +{ +  char buf[1024]; + +	va_list argp; +	va_start(argp, fmt); +	vsprintf(buf, fmt, argp); +	va_end(argp); + +  showmsg(buf, TXT_INFO_TITLE, ICON_INFO); + +  log("Info: %s", buf); +} + + +#endif/*USE_GUI*/ diff --git a/client/info_gui.h b/client/info_gui.h new file mode 100644 index 0000000..a4f5135 --- /dev/null +++ b/client/info_gui.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            info_gui.h + * + *  Tue May  3 09:34:59 CEST 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifndef __MIAV_INFO_GUI_H__ +#define __MIAV_INFO_GUI_H__ + +#ifdef USE_GUI + +#define TXT_ERROR_TITLE "Der er opstĺet en fejl!" +#define TXT_WARNING_TITLE "Advarsel" +#define TXT_INFO_TITLE "Information" + +#include "info.h" + +#include "miav_config.h" + +#include <qwidget.h> +#include <qapplication.h> + +#include <pthread.h> +#include <semaphore.h> + +#include "messagebox.h" + +#define TYPE_SHOW_MESSAGEBOX 65432 + +class ShowMessageEvent : public QCustomEvent { +public: +  ShowMessageEvent( MessageBox* msgbox ) +    : QCustomEvent( TYPE_SHOW_MESSAGEBOX ), m( msgbox ) {} +  MessageBox *messagebox() const { return m; } +private: +  MessageBox *m;; +}; + +class InfoEventHandler : public QObject { +protected: +  bool eventFilter( QObject *o, QEvent *e ); +}; + + +class InfoGui: public Info { +public: +  InfoGui(QApplication *a, QWidget *p, MiavConfig *config); +  ~InfoGui(); + +  void error(char* fmt, ...); +  void warn(char* fmt, ...); +  void info(char* fmt, ...); + +  void setParent(QWidget *p); + +private: +  void showmsg(char *msg, char *title, msg_icon icon); + +  QApplication *qapp; +  QWidget *parent; +}; + +#endif/*__MIAV_INFO_GUI_H__*/ + +#endif/*USE_GUI*/ diff --git a/client/mainwindow.cc b/client/mainwindow.cc new file mode 100644 index 0000000..ce3d9bb --- /dev/null +++ b/client/mainwindow.cc @@ -0,0 +1,575 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            mainwindow.cc + * + *  Sat Aug 21 19:49:34 2004 + *  Copyright  2004  deva + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "mainwindow.h" + +#include <qpainter.h> +#include <qpicture.h> + +#include <qpushbutton.h> +#include <qfont.h> +#include <qpixmap.h> +#include <qbitmap.h> +#include <qimage.h> +#include <qlayout.h> +#include <qgroupbox.h> + +#include <qstatusbar.h> + +#include <math.h> + +//#include "mgui_alert.h" +//#include "mgui_datasocket.h" + +#include "miav_config.h" + +#include <config.h> +//"miav-grab.h" + +//#define WITH_DV +MainWindow::MainWindow(QApplication *qApp, QWidget* parent, const char* name ) +	: QWidget( parent, name, WStyle_Customize | WStyle_NoBorder ) +{ +  info = new InfoGui(qApp, this, config); + +  info->log("Starting MIaV v. %s.", VERSION); + +  video_width = config->readInt("video_width"); +  video_height = config->readInt("video_height"); + +  int resolution_w = config->readInt("pixel_width"); +  int resolution_h = config->readInt("pixel_height"); + +  unit = ((float)resolution_w / config->readFloat("screensize")) / INCH_IN_CM; + +  printf("Unit: %f\n", unit); + +  move(0,0); +  resize(resolution_w, resolution_h); + +  // Load icons +  img_record = loadButtonIcon( PIXMAP_RECORD ); +  img_stop = loadButtonIcon( PIXMAP_STOP ); +  img_freeze = loadButtonIcon( PIXMAP_FREEZE ); +  img_unfreeze = loadButtonIcon( PIXMAP_UNFREEZE ); +  img_cpr = loadButtonIcon( PIXMAP_CPR ); +  img_clear = loadButtonIcon( PIXMAP_CLEAR ); +  img_snapshot = loadButtonIcon( PIXMAP_SNAPSHOT ); +  img_logo = loadButtonIcon( PIXMAP_LOGO_SMALL, 1 ); +  img_mute = loadButtonIcon( PIXMAP_MUTE ); +  img_unmute = loadButtonIcon( PIXMAP_UNMUTE ); + +  img_dummy = loadImage( PIXMAP_DUMMY ); +   +  timer = new QTimer(this); +  connect(timer, SIGNAL(timeout()), SLOT(redraw_edge())); +  rec_edge_counter = 0.0f; + +  // This must be defined before the gui i created (img_live uses it as parameter) +  camera = new Camera(info); + +  createGui(); +  show(); + +  camera->connect(config->readString("server_addr")->c_str(),  +                  config->readInt("server_port"), +                  img_live->width(), img_live->height()); + +  // Make sure this is created *after* the camera object! +  taskbartimer = new QTimer(this); +  connect(taskbartimer, SIGNAL(timeout()), SLOT(taskbar_update())); +  taskbartimer->start(200); + +  recording = false; +  frozen = false; +  muted = false; + +  info->log("MIaV is ready."); + +  // Open the CPR Dialog +  cpr_clicked(); + +} + +MainWindow::~MainWindow() +{ +  info->log("MIaV is shutting down."); + +  delete img_history; +  delete camera; +  delete btn_cpr; + +  info->log("MIaV is shut down."); +} + +QImage *MainWindow::loadButtonIcon( char *name, int height ) +{ + +  QImage scaled; +  QImage *img; + +  img = new QImage(); +  img->load( name ); + +  int h = (int)(height * unit); +  int w = (int)((float)img->width() / (float)(img->height() / (float)h)); + +  scaled = img->smoothScale(w, h); +  delete img; +  img = new QImage(scaled); + +  return img; +} + +QImage *MainWindow::loadImage( char *name ) +{ +  QImage *img; + +  img = new QImage(); +  img->load( name ); + +  return img; +} + +void MainWindow::createGui() +{ +  // Layout widgets + +  /*  __________________________________________________ +   *(0) ___________________________  |  ______________  | +   * | |      |      |      |      | | |              | | +   * |(1)     |      |      |      | |(2)             | | +   * | |      |      |      |      | | |              | | +   * | |      |      |      |      | | |              | | +   * | |      |      |      |      | | |______________| | +   * | |      |      |      |      | | |              | | +   * | |      |      |      |      | | |              | | +   * | |      |      |      |      | | |              | | +   * | |______|______|______|______| | |              | | +   * | |      |      |      |      | | |______________| | +   * | |______|______|______|______| | |              | | +   * | |      |      |      |      | | |              | | +   * | |______|______|______|______| | |              | | +   * | |      |      |      |      | | |              | | +   * | |______|______|______|______| | |______________| | +   * |_______________________________|__________________| +   * |_______________________________|__________________| +   */ + +	QGridLayout *g0 = new QGridLayout(this, 2, 2, 0, -1); +	QGridLayout *g1 = new QGridLayout(4, 4, -1); +  g0->addLayout(g1, 0, 0); + +  QGroupBox *gb = new QGroupBox(this); +  //  gb->setRows(NUM_HISTORY); +  gb->setColumns(1); +  //  gb->setTitle("fisk"); +  //	QGridLayout *g2 = new QGridLayout(1, NUM_HISTORY, -1); +  //	QVBoxLayout *g2 = new QVBoxLayout(this); +  //  g0->addLayout(g2, 0, 1); + +  gb->setInsideMargin(HISTORY_LIST_MARGIN); +  gb->setInsideSpacing(HISTORY_LIST_SPACING); +  gb->setFlat(true); +  g0->addWidget(gb, 0, 1); + +  int resolution_w = config->readInt("pixel_width"); +  int resolution_h = config->readInt("pixel_height"); + +  int output_width = resolution_w - // this->width() -  +    (int)(BUTTON_WIDTH * unit) -  +    (gb->insideMargin() * 2) -  +    g1->margin() * 2 - +    g0->margin() * 2; + +  int output_height = resolution_h - // this->height() -  +    (int)(3 * BUTTON_HEIGHT * unit) -  +    g1->margin() * 5 - +    g0->margin() * 3; + +  img_recedge = new QLabel(this); +  img_recedge->setBackgroundColor(QColor(160,160,160)); +  img_recedge->setFixedSize(output_width, output_height); +   +  img_live = new VideoWidget(img_recedge, camera); +  img_live->setFixedSize(output_width - 20, output_height - 20); +  img_live->move(10,10); +  g1->addMultiCellWidget ( img_recedge, 0, 0, 0, 3, Qt::AlignHCenter); +  //  QObject::connect( img_live, SIGNAL(clicked()), this, SLOT(live_clicked()) ); + +  // CPR/NAME LABEL + CPR button +  lbl_cpr = createLabel("", output_width - (int)(BUTTON_WIDTH * unit), BUTTON_HEIGHT); +  g1->addMultiCellWidget ( lbl_cpr, 1, 1, 0, 2); + +  btn_cpr = createButton(""); +  btn_cpr->setFocus(); +  btn_cpr->setPixmap(*img_cpr); +  QObject::connect( btn_cpr, SIGNAL(clicked()), this, SLOT(cpr_clicked()) ); +  // Will also be connected in the MGUI code +  g1->addWidget(btn_cpr, 1, 3); + +  lbl_name = createLabel("",  output_width, (int)(BUTTON_HEIGHT * 0.8f)); +  g1->addMultiCellWidget ( lbl_name, 2, 2, 0, 3); +/* +  btn_clear = createButton(""); +  btn_clear->setPixmap(*img_clear); +  QObject::connect( btn_clear, SIGNAL(clicked()), this, SLOT(clear_clicked()) ); +  // Will also be connected in the MGUI code +  g1->addWidget(btn_clear, 1, 2); +*/ +  // Rec + Shot + Freeze buttons +  btn_rec = createButton(""); +  btn_rec->setPixmap(*img_record); +  QObject::connect( btn_rec, SIGNAL(clicked()), this, SLOT(rec_clicked()) ); +  g1->addWidget(btn_rec, 3, 0); +   +  btn_shoot = createButton(""); +  btn_shoot->setPixmap(*img_snapshot); +  QObject::connect( btn_shoot, SIGNAL(clicked()), this, SLOT(shoot_clicked()) ); +  g1->addWidget(btn_shoot, 3, 1); +   +  btn_freeze = createButton(""); +  btn_freeze->setPixmap(*img_freeze); +  QObject::connect( btn_freeze, SIGNAL(clicked()), this, SLOT(freeze_clicked()) ); +  g1->addWidget(btn_freeze, 3, 2); +   +  btn_mute = createButton(""); +  btn_mute->setPixmap(*img_unmute); +  QObject::connect( btn_mute, SIGNAL(clicked()), this, SLOT(mute_clicked()) ); +  g1->addWidget(btn_mute, 3, 3); +   +  // History widgets +  int w = (int)((float)BUTTON_WIDTH * unit); +  int h = (int)(576.0f / (720.0f / ((float)BUTTON_WIDTH * unit))); + +  int window_height = config->readInt("pixel_height"); +  this->num_history = (window_height -  +                       ((int)unit * BUTTON_HEIGHT + HISTORY_LIST_SPACING ) -  +                       (2 * HISTORY_LIST_MARGIN)) / (h + HISTORY_LIST_SPACING); +  img_history = new HistoryWidget*[this->num_history]; + +  for(unsigned int i = 0; i < num_history; i++) { +    img_history[i] = new HistoryWidget(gb); +    img_history[i]->set_image(img_dummy); +    img_history[i]->setFixedSize(w, h); +  } + +  // Clear button +  btn_clear = createButton("", gb); +  btn_clear->setPixmap(*img_clear); +  QObject::connect( btn_clear, SIGNAL(clicked()), this, SLOT(clear_clicked()) ); + +  // Statusbar +  status = new QStatusBar(this); +  status->setSizeGripEnabled(FALSE); +  //  status->setFont(QFont( "Sans Serif", (int)(unit * height / 3), QFont::Normal )); +  g0->addMultiCellWidget(status, 4, 4, 0, 1); + +  lbl_recordtime = createLabel("", BUTTON_WIDTH, 1); +  lbl_recordtime->setFixedWidth((int)(BUTTON_WIDTH * unit) +  +                                (gb->insideMargin() * 2) +  +                                g1->margin() * 2 + +                                g0->margin() * 2); +  status->addWidget(lbl_recordtime, 0, TRUE); + +  // About button +  btn_about = new QPushButton("", this); +  btn_about->setFixedHeight((int)unit); +  btn_about->setPixmap(*img_logo); +  QObject::connect( btn_about, SIGNAL(clicked()), this, SLOT(about_clicked()) ); +  status->addWidget(btn_about, 0, TRUE); + +  // Version label +  lbl_version = createLabel("MIaV-Grab v" VERSION, BUTTON_WIDTH, 1); +  lbl_version->setFixedWidth((int)(BUTTON_WIDTH * unit) + +                                (gb->insideMargin() * 2) +  +                                g1->margin() * 2 + +                                g0->margin() * 2); +  status->addWidget(lbl_version, 0, TRUE); + +  status->message( TXT_READY ); +} + + +QPushButton *MainWindow::createButton(char *caption, int width, int height) +{ +  return createButton(caption, this);//, width, height); +} + + +QPushButton *MainWindow::createButton(char *caption, QWidget *parent, int width, int height) +{ +  QPushButton *btn = new QPushButton(caption, parent); +  btn->setFont( QFont( "Sans Serif", (int)(unit * height / 2), QFont::Bold ) ); +  btn->setFixedHeight((int)(unit * height)); +  //  btn->setFixedWidth((int)(unit * width)); +  return btn; +} + + +QLabel *MainWindow::createLabel(char *caption, int width, int height) +{ +  QLabel *lbl = new QLabel(caption, this); +  lbl->setFont( QFont( "Sans Serif",  +                       //(height>1)?(int)(unit * height / 2):(int)(unit * height / 2),  +                       (int)(unit * height / 2),  +                       (height>1)?QFont::Bold:QFont::Normal ) ); +  lbl->setFixedHeight((int)(unit * height)); +  //  lbl->setFixedWidth((int)(unit * width)); +  return lbl; +} + +#include <sys/time.h> +static struct timeval starttime;  +static int h = 0; +static int m = 0; +static int s = 0; +static int watchdog = 0; + +void MainWindow::taskbar_update() +{ +  struct timeval time; +  watchdog++; + +  if(recording) { +    if((watchdog % 300 == 0) || ((camera->getQueueLength() > 1000) && (watchdog % 50 == 0)))  +      info->log("Queue length: %d (active)", camera->getQueueLength()); + +    gettimeofday(&time, NULL); +     +    s = time.tv_sec - starttime.tv_sec; + +    h = s / (60 * 60); +    s -= h * (60 * 60); +    m = s / 60; +    s -= m * 60; +  } else { +    if((camera->getQueueLength() > 0)  && (watchdog % 300 == 0)) +      info->log("Queue length: %d (passive)", camera->getQueueLength()); +    gettimeofday(&starttime, NULL); +  } + +  char msg[256]; +  int l = camera->getQueueLength(); +  sprintf(msg, TXT_TIME " %.02d:%.02d:%.02d " TXT_QUEUELENGTH " %d", h, m, s, l); +  lbl_recordtime->setText(msg); +} + +#define GREY 160 +#define SPEED 0.07f +void MainWindow::redraw_edge() +{ +  rec_edge_counter += SPEED; +  float val = fabs(sin(rec_edge_counter)); +  img_recedge->setBackgroundColor(QColor((int) ((255 - GREY) * val + GREY), +                                         (int) (GREY - (GREY * val)), +                                         (int) (GREY - (GREY * val)))); +} + +void MainWindow::message(char *msg) +{ +  status->message(msg); +  info->log("Message: %s", msg); +} + +void MainWindow::clear() +{ +  info->log("Clearing screen."); + + +  // History widgets +  for(unsigned int i = 0; i < num_history; i++) { +    img_history[i]->set_image(img_dummy); +  } + +  lbl_name->setText(""); +  lbl_cpr->setText(""); +} + +#include "aboutwindow.h" +void MainWindow::about_clicked() +{ +  AboutWindow about; +  about.exec(); +} + +void MainWindow::clear_clicked() +{ +  if(MessageBox(this,  +                TXT_ASK_CLEAR_SCREEN_TITLE,  +                TXT_ASK_CLEAR_SCREEN,  +                TYPE_YES_NO,  +                ICON_QUESTION).exec() == MSG_YES) { +    clear(); +  } +} + +void MainWindow::cpr_clicked() +{ +  char oldcpr[256]; +  char oldname[256]; + +  // If recording, stop recording before changingcpr +  if(recording) { +    MessageBox(this,  +               TXT_STOP_RECORDING_TITLE,  +               TXT_STOP_RECORDING,  +               TYPE_OK,  +               ICON_WARNING).exec(); +    return; +  } +  info->log("Activated CPR chooser."); + +  // Save CPR and name, from the labels. +  strcpy(oldname, lbl_name->text().ascii()); +  strcpy(oldcpr, lbl_cpr->text().ascii()); + +  clear(); + +  // Create and call the CPRQueryDialog. +  CPRQueryDialog dlg(info, lbl_cpr, lbl_name, this, TXT_CPRDLG_TITLE, status); + +  if(dlg.exec() == 0) { +    // Restore old CPR and name, in the labels.  +    lbl_name->setText(oldname); +    lbl_cpr->setText(oldcpr); +    info->log("Cancelled CPR chooser."); +  } else { +    // Change CPR camera. +    info->log("New CPR %s (old %s).", (char*)lbl_cpr->text().ascii(), oldcpr); +    strcpy(oldname, lbl_name->text().ascii()); +    strcpy(oldcpr, lbl_cpr->text().ascii()); +    clear(); +    lbl_name->setText(oldname); +    lbl_cpr->setText(oldcpr); +    camera->setCpr((char*)lbl_cpr->text().ascii(), (char*)lbl_name->text().ascii()); +  } +} + +void MainWindow::rec_clicked() +{ +  if(!recording) { +    info->log("Start recording."); +    recording = 1; +    // Start flashing the edge +    rec_edge_counter = 0.0f; +    timer->start(100); +    btn_rec->setPixmap(*img_stop); +    camera->start(); +  } else { +    switch(MessageBox(this,  +                      TXT_ASK_SAVE_TITLE,  +                      TXT_ASK_SAVE,  +                      TYPE_YES_NO_MAYBE_CANCEL,  +                      ICON_QUESTION).exec()) { +    case MSG_YES: +      info->log("Stop recording (Said yes to save)."); +      recording = 0; +      camera->stop(SAVE); +      timer->stop(); +      img_recedge->setBackgroundColor(QColor(160,160,160)); +      btn_rec->setPixmap(*img_record); +      break; + +    case MSG_NO: +      info->log("Stop recording (Said no to save)."); +      recording = 0; +      camera->stop(DELETE); +      timer->stop(); +      img_recedge->setBackgroundColor(QColor(160,160,160)); +      btn_rec->setPixmap(*img_record); +      break; + +    case MSG_MAYBE: +      info->log("Stop recording (Said maybe to save)."); +      recording = 0; +      camera->stop(LATER); +      timer->stop(); +      img_recedge->setBackgroundColor(QColor(160,160,160)); +      btn_rec->setPixmap(*img_record); +      break; + +    case MSG_CANCEL: +      info->log("Didn't stop recording (canceled)."); +      break; +    } +  } +} + +void MainWindow::shoot_clicked() +{ +  //  unsigned char pixels[720*576*3]; +  info->log("Snapshot (%s).", frozen?"frozen":"unfrozen"); + +  QImage screenshot(720, 576, 32); + +  camera->snapshot(screenshot.bits()); + +  QImage *image; +  for(int cnt = (num_history-1); cnt > 0; cnt--) { +    image = img_history[cnt-1]->get_image(); +    img_history[cnt]->set_image(image); +  } +  img_history[0]->set_image(&screenshot); + +  if(frozen) { +    camera->unfreeze(); +    btn_freeze->setPixmap(*img_freeze); +    btn_freeze->setOn(false); +    frozen = false; +  } +} + +void MainWindow::freeze_clicked() +{ +  if(frozen) { +    info->log("Unfreeze."); +    camera->unfreeze(); +    btn_freeze->setPixmap(*img_freeze); +    btn_freeze->setOn(false); +    frozen = false; +  } else { +    info->log("Freeze."); +    camera->freeze(); +    btn_freeze->setPixmap(*img_unfreeze); +    btn_freeze->setOn(true); +    frozen = true; +  } +} + +void MainWindow::mute_clicked() +{ +  muted = !muted; +  if(muted) btn_mute->setPixmap(*img_mute); +  else btn_mute->setPixmap(*img_unmute); + +  camera->setMute(muted); +} + +#endif /*USE_GUI*/ diff --git a/client/mainwindow.h b/client/mainwindow.h new file mode 100644 index 0000000..2ac7d82 --- /dev/null +++ b/client/mainwindow.h @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            mainwindow.h + * + *  Sat Aug 21 19:50:13 2004 + *  Copyright  2004  deva + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +  +#ifndef __MAINWINDOW_H__ +#define __MAINWINDOW_H__ + +#include <string> +using namespace std; + +#include <qwidget.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qstatusbar.h> +#include <qtimer.h> +#include <qpixmap.h> +#include <qimage.h> + +#include "videowidget.h" +#include "camera.h" +#include "cprquerydialog.h" +#include "historywidget.h" + +#include "info_gui.h" + +#define INCH_IN_CM 2.54f + +/** + * First some GUI specs + */ +//#define NUM_HISTORY 3 // moved to a genuine variable +// Button sizes in cm (metric) +#define BUTTON_WIDTH 7 +#define BUTTON_HEIGHT 2 + +#define HISTORY_LIST_MARGIN 25 +#define HISTORY_LIST_SPACING 5 + +/**  + * Textstrings + */ +#define TXT_ERROR_TITLE "Der er opstĺet en fejl!" +#define TXT_READY "Klar..." +#define TXT_CPRDLG_TITLE "CPRQueryDialog" +#define TXT_ASK_SAVE_TITLE "Vil du gemme filmen?" +#define TXT_ASK_SAVE "Vil du gemme filmen permanent?" +#define TXT_STOP_RECORDING_TITLE "Stop optagelsen" +#define TXT_STOP_RECORDING "Optagelsen skal standses, inden et nyt cpr nummer kan indtastes.\n\ +Optagelsen standses ved tryk pĺ den rřde cirkel med gul streg over." +#define TXT_TIME "Tid:" +#define TXT_QUEUELENGTH "Buffer střrelse:" +#define TXT_ASK_CLEAR_SCREEN_TITLE "Fjerne data fra skćrmen?" +#define TXT_ASK_CLEAR_SCREEN "Er du sikker pĺ at du vil dataene fra skćrmen (billeder, CPR nummer og navn)?" +    +/**  + * Images + */ +#define PIXMAP_MUTE       PIXMAPS"/mute.png" +#define PIXMAP_UNMUTE     PIXMAPS"/unmute.png" + +#define PIXMAP_RECORD     PIXMAPS"/record.png" +#define PIXMAP_STOP       PIXMAPS"/stop.png" + +#define PIXMAP_FREEZE     PIXMAPS"/freeze.png" +#define PIXMAP_UNFREEZE   PIXMAPS"/unfreeze.png" + +#define PIXMAP_CPR        PIXMAPS"/cpr.png" +#define PIXMAP_CLEAR      PIXMAPS"/clear.png" + +#define PIXMAP_SNAPSHOT   PIXMAPS"/snapshot.png" +#define PIXMAP_DUMMY      PIXMAPS"/dummy.png" +#define PIXMAP_LOGO_SMALL PIXMAPS"/miav-logo.png" + +class MainWindow : public QWidget +{ +  Q_OBJECT +public: +  MainWindow(QApplication *qApp, QWidget* parent = 0, const char* name = 0); +  ~MainWindow(); +   +  void message(char* msg); + +public slots: +  void cpr_clicked(); +  void clear_clicked(); +  void rec_clicked(); +  void shoot_clicked(); +  void freeze_clicked(); +  void redraw_edge(); +  void taskbar_update(); +  void about_clicked(); +  void mute_clicked(); +  +private: +  unsigned int num_history; + +  void clear(); + +  Info *info; + +  void createGui(); +   +  Camera *camera; +  Info *cam_info; + +  // Image loading routines. +  QImage *loadButtonIcon( char *name, int height = BUTTON_HEIGHT ); +  QImage *loadImage( char *name ); + +  QImage *img_unfreeze; +  QImage *img_freeze; +  QImage *img_snapshot; +  QImage *img_cpr; +  QImage *img_clear; +  QImage *img_record; +  QImage *img_stop; +  QImage *img_logo; +  QImage *img_mute; +  QImage *img_unmute; + +  QImage *img_dummy; +   +  QLabel *lbl_version; +  QLabel *lbl_cpr; +  QLabel *lbl_name; +  QLabel *lbl_recordtime; + +  QTimer *taskbartimer; + +  // Used for the check_for_error_once_per_2_seconds (very ugly) +  QTimer *errtimer; + +  float rec_edge_counter; +  QTimer *timer; +  QLabel *img_recedge; +  HistoryWidget **img_history; +   +  QPushButton *btn_logo; +  QPushButton *btn_clear; +  QPushButton *btn_cpr; +  QPushButton *btn_rec; +  QPushButton *btn_shoot; +  QPushButton *btn_freeze; +  QPushButton *btn_mute; + +  QPushButton *btn_about; + +  QStatusBar *status; +   +  VideoWidget *img_live; +   +  bool recording; +  bool frozen; +  bool muted; + +  // Configuration values +  float unit; +  int video_width; +  int video_height; + +  QPushButton *createButton(char *caption, int width = BUTTON_WIDTH, int height = BUTTON_HEIGHT); +  QPushButton *createButton(char *caption, QWidget *parent, int width = BUTTON_WIDTH, int height = BUTTON_HEIGHT); +  QLabel *createLabel(char *caption, int width, int height); +}; + +#endif + +#endif /*USE_GUI*/ diff --git a/client/messagebox.cc b/client/messagebox.cc new file mode 100644 index 0000000..fd812eb --- /dev/null +++ b/client/messagebox.cc @@ -0,0 +1,245 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            messagebox.cc + * + *  Fri Feb 25 20:23:19 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI +#include "messagebox.h" +#include "miav_config.h" + +// For button sizes! +#include "mainwindow.h" + +//////////////////////////////////////////////////////////////////////////////////////// +/* If the cpr input by the user is not valid, this dialog + * ask the user what to do. Edit the number, use it as it is,  + * or clear the number. + */ + +MessageBox::MessageBox(QWidget* parent,  +                       const char* name,  +                       const char* text,  +                       msg_type type,  +                       msg_icon icon) +	: QDialog(parent, name, TRUE) +{ +  int resolution_w = config->readInt("pixel_width"); +  //int resolution_h = config->readInt("pixel_height"); +  unit = ((float)resolution_w / config->readFloat("screensize")) / INCH_IN_CM; + + +  setCaption(name); +	QFrame *topf = new QFrame(this); +  topf->setFrameStyle(QFrame::Box | QFrame::Raised); +  topf->setLineWidth(3);	 +	QVBoxLayout *bl = new QVBoxLayout(this); +	bl->addWidget(topf); +	 +  // Setup the icon +  pix_icon = new QPixmap(); +  switch(icon) { +  case ICON_NONE:    // No icon is used +    { +      break; +    } +  case ICON_DEFAULT: // An icon matching the buttons is used +    { +      switch(type) { +      case TYPE_OK: +        pix_icon->load( PIXMAP_INFO ); +        break; +      case TYPE_OK_CANCEL:  +        pix_icon->load( PIXMAP_WARNING ); +        break; +      case TYPE_YES_NO:  +      case TYPE_YES_NO_MAYBE:  +      case TYPE_YES_NO_CANCEL:  +      case TYPE_YES_NO_MAYBE_CANCEL:  +        pix_icon->load( PIXMAP_QUESTION ); +        break; +      } +      break; +    } +  case ICON_INFO:    // An info icon (matching the ok button) +    { +      pix_icon->load( PIXMAP_INFO ); +      break; +    } +  case ICON_WARNING:    // An warning icon (matching the ok/cancel button) +    { +      pix_icon->load( PIXMAP_WARNING ); +      break; +    } +  case ICON_ERROR:   // An critical error  icon +    { +      pix_icon->load( PIXMAP_ERROR ); +      break; +    } +  case ICON_QUESTION:// An question icon (matching the yes/no and yes/no/cancel buttons) +    { +      pix_icon->load( PIXMAP_QUESTION ); +      break; +    } +  } +  QLabel *lbl_icon = new QLabel(topf); +  lbl_icon->setPixmap(*pix_icon); + +	QLabel *lbl_text = new QLabel(topf); +	lbl_text->setText(text); +  lbl_text->setFont( QFont( "Sans Serif",  +                       //(height>1)?(int)(unit * height / 2):(int)(unit * height / 2),  +                       (int)(unit * 0.7 * BUTTON_HEIGHT / 2),  +                       QFont::Normal ) ); +  lbl_text->setFixedHeight((int)(unit * BUTTON_HEIGHT)); +  //	lbl_text->setFont(QFont("Arial", 18)); +	QFrame *f = new QFrame(topf); + +	QVBoxLayout *blayout = new QVBoxLayout(topf, 20, 20); + +  blayout->addWidget(lbl_icon); +	blayout->addWidget(lbl_text); +	blayout->addWidget(f); + +  // Setup the buttons +  switch(type) { +  case TYPE_OK:  +    { +      QPushButton *bok = createButton(f, TXT_OK ); +      QGridLayout *glayout = new QGridLayout(f, 1, 1, 20, 20); +      glayout->addWidget(bok, 0, 0); +      connect(bok, SIGNAL( clicked() ), SLOT(bok_clicked()));	 +      break; +    } +  case TYPE_OK_CANCEL:  +    { +      QPushButton *bok = createButton(f, TXT_OK ); +      QPushButton *bcancel = createButton(f, TXT_CANCEL ); +      QGridLayout *glayout = new QGridLayout(f, 1, 2, 20, 20); +      glayout->addWidget(bcancel, 0, 1); +      glayout->addWidget(bok, 0, 2); +      connect(bcancel, SIGNAL( clicked() ), SLOT(bcancel_clicked()));	 +      connect(bok, SIGNAL( clicked() ), SLOT(bok_clicked()));	 +      break; +    } +  case TYPE_YES_NO:  +    { +      QPushButton *bno = createButton(f, TXT_NO ); +      QPushButton *byes = createButton(f, TXT_YES ); +      QGridLayout *glayout = new QGridLayout(f, 1, 2, 20, 20); +      glayout->addWidget(bno, 0, 0); +      glayout->addWidget(byes, 0, 1); +      connect(byes, SIGNAL( clicked() ), SLOT(byes_clicked())); +      connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));	 +      break; +    } +  case TYPE_YES_NO_MAYBE:  +    { +      QPushButton *bmaybe = createButton(f, TXT_MAYBE ); +      QPushButton *bno = createButton(f, TXT_NO ); +      QPushButton *byes = createButton(f, TXT_YES ); +      QGridLayout *glayout = new QGridLayout(f, 1, 3, 20, 20); +      glayout->addWidget(bno, 0, 0); +      glayout->addWidget(byes, 0, 1); +      glayout->addWidget(bmaybe, 0, 2); +      connect(byes, SIGNAL( clicked() ), SLOT(byes_clicked())); +      connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));	 +      connect(bmaybe, SIGNAL( clicked() ), SLOT(bmaybe_clicked()));	 +      break; +    } +  case TYPE_YES_NO_CANCEL:  +    { +      QPushButton *bcancel = createButton(f, TXT_CANCEL ); +      QPushButton *bno = createButton(f, TXT_NO ); +      QPushButton *byes = createButton(f, TXT_YES ); +      QGridLayout *glayout = new QGridLayout(f, 1, 3, 20, 20); +      glayout->addWidget(bno, 0, 0); +      glayout->addWidget(bcancel, 0, 1); +      glayout->addWidget(byes, 0, 2); +      connect(byes, SIGNAL( clicked() ), SLOT(byes_clicked())); +      connect(bcancel, SIGNAL( clicked() ), SLOT(bcancel_clicked()));	 +      connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));	 +      break; +    } +  case TYPE_YES_NO_MAYBE_CANCEL:  +    { +      QPushButton *bmaybe = createButton(f, TXT_MAYBE ); +      QPushButton *bcancel = createButton(f, TXT_CANCEL ); +      QPushButton *bno = createButton(f, TXT_NO ); +      QPushButton *byes = createButton(f, TXT_YES ); +      QGridLayout *glayout = new QGridLayout(f, 1, 4, 20, 20); +      glayout->addWidget(bno, 0, 0); +      glayout->addWidget(bcancel, 0, 1); +      glayout->addWidget(byes, 0, 2); +      glayout->addWidget(bmaybe, 0, 3); +      connect(bmaybe, SIGNAL( clicked() ), SLOT(bmaybe_clicked())); +      connect(byes, SIGNAL( clicked() ), SLOT(byes_clicked())); +      connect(bcancel, SIGNAL( clicked() ), SLOT(bcancel_clicked()));	 +      connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));	 +      break; +    } +  } + +} + +MessageBox::~MessageBox()  +{ +  delete pix_icon; +} + +QPushButton *MessageBox::createButton(QWidget *parent, const char *text) +{ +	QPushButton *q = new QPushButton(parent); +	q->setText(text); +  q->setFont( QFont( "Sans Serif", (int)(unit * 0.7 * BUTTON_HEIGHT / 2 ), QFont::Normal ) ); +	q->setFixedSize((int)(BUTTON_WIDTH * unit), (int)(BUTTON_HEIGHT * unit)); +	return q; +} + +void MessageBox::bok_clicked()  +{ +	done(MSG_OK); +}	 + +void MessageBox::bcancel_clicked()  +{ +	done(MSG_CANCEL); +}	 + +void MessageBox::byes_clicked()  +{ +	done(MSG_YES); +}	 + +void MessageBox::bno_clicked()  +{ +	done(MSG_NO); +}	 + +void MessageBox::bmaybe_clicked()  +{ +	done(MSG_MAYBE); +}	 + +#endif/*USE_GUI*/ diff --git a/client/messagebox.h b/client/messagebox.h new file mode 100644 index 0000000..30a8307 --- /dev/null +++ b/client/messagebox.h @@ -0,0 +1,112 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            messagebox.h + * + *  Fri Feb 25 20:23:19 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __MIAV_MESSAGEBOX_H__ +#define __MIAV_MESSAGEBOX_H__ + +#include <qdialog.h> +#include <qwidget.h> +#include <qframe.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qlabel.h> +#include <qpixmap.h> + +typedef enum { +  ICON_NONE,    // No icon is used +  ICON_DEFAULT, // An icon matching the buttons is used +  ICON_INFO,    // An info icon (matching the ok button) +  ICON_WARNING, // An warning icon (matching the ok/cancel button) +  ICON_ERROR,   // An critical error icon +  ICON_QUESTION // An question icon (matching the yes/no and yes/no/cancel buttons) +} msg_icon; + +typedef enum { +  MSG_YES, +  MSG_NO, +  MSG_CANCEL, +  MSG_OK, +  MSG_MAYBE +} msg_val; + +typedef enum { +  TYPE_OK, +  TYPE_OK_CANCEL, +  TYPE_YES_NO, +  TYPE_YES_NO_MAYBE, +  TYPE_YES_NO_CANCEL, +  TYPE_YES_NO_MAYBE_CANCEL, +} msg_type; + + +/**  + * Textstrings + */ +#define TXT_OK     "Ok" +#define TXT_CANCEL "Annullér" +#define TXT_YES    "Ja" +#define TXT_NO     "Nej" +#define TXT_MAYBE  "Mĺske" + +/**  + * Images + */ +#define PIXMAP_INFO     PIXMAPS"/info.png" +#define PIXMAP_WARNING  PIXMAPS"/warning.png" +#define PIXMAP_QUESTION PIXMAPS"/question.png" +#define PIXMAP_ERROR    PIXMAPS"/error.png" + + +class MessageBox : public QDialog +{ +	Q_OBJECT +public: +	MessageBox(QWidget* parent = 0,  +             const char* name = "",  +             const char* text = "",  +             msg_type type = TYPE_OK,  +             msg_icon icon = ICON_DEFAULT); +	~MessageBox(); + +public slots: +  void bok_clicked(); +  void bcancel_clicked(); +  void byes_clicked(); +  void bno_clicked(); +  void bmaybe_clicked(); + +private: +  float unit; +  QPixmap *pix_icon; +  QPushButton *createButton(QWidget *parent, const char *text); +}; + +#endif/*__MIAV_MESSAGEBOX_H__*/ + +#endif /*USE_GUI*/ diff --git a/client/miav_client.cc b/client/miav_client.cc new file mode 100644 index 0000000..a8e9f7c --- /dev/null +++ b/client/miav_client.cc @@ -0,0 +1,60 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            miav.cc + * + *  Sat Aug 21 17:32:24 2004 + *  Copyright  2004  deva + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> + +#include "miav_client.h" + +#include <QApplication> +#include <stdio.h> + +#include "mainwindow.h" +#include "miav_config.h" +#include "info_gui.h" + + +QApplication *miav_app; + +/**  + * This function starts the MIaV gui. + */ +int main(int argc, char *argv[]) +  QApplication miav_grab( argc, argv ); +  miav_app = &miav_grab; + +  MiavConfig cfg(ETC"/miav.conf", NULL); +  InfoGui info(&miav_grab, NULL, &cfg); +  config = new MiavConfig(ETC"/miav.conf", &info); + +  InfoEventHandler *eventhandler = new InfoEventHandler( ); +  miav_grab.installEventFilter( eventhandler ); +   +  MainWindow mainwindow( &miav_grab ); +  miav_grab.setMainWidget( &mainwindow ); + +  info.setParent(&mainwindow); +  return miav_grab.exec(); +} diff --git a/client/miav_client.h b/client/miav_client.h new file mode 100644 index 0000000..ce7842a --- /dev/null +++ b/client/miav_client.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            miav.h + * + *  Mon Nov  8 09:59:24 CET 2004 + *  Copyright  2004 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifndef __LIBMIAV_H__ +#define __LIBMIAV_H__ + +#include "util.h" + +#include "network.h" +#include "socket.h" +#include "queue.h" + +#ifdef USE_GUI +#include <qapplication.h> +extern QApplication *miav_app; +#endif/*USE_GUI*/ + +#endif/*__LIBMIAV_H__*/ diff --git a/client/player.cc b/client/player.cc new file mode 100644 index 0000000..e57211d --- /dev/null +++ b/client/player.cc @@ -0,0 +1,322 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            plsyer.cc + * + *  Wed Nov  3 21:23:14 CET 2004 + *  Copyright  2004 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  B. Stultiens + * Copyright (C) 2004  Koen Otter and Glenn van der Meyden + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> +#ifdef USE_GUI + +#include "player.h" + +// Use libdv +#include <libdv/dv.h> +#include <libdv/dv_types.h> + +#include <time.h> + +// For sleep +#include <unistd.h> + +Player::Player(Info *ginfo, +               int w, int h, +               volatile int *grunning, +               sem_t	*gsem, +               Queue<Frame> *gqueue, +               pthread_mutex_t *gmutex) +{ +  // No errors has ocurred... yet! +  noErrors = true; +   +  yuv_draw = new YUVDraw(); + +  width = w; +  height = h; + +  info = ginfo; + +  running = grunning; +  sem = gsem; +  queue = gqueue; +  mutex = gmutex; + + 	sem_init(&play_sem, 0, 1); + +  initSDL(); + +  bypass = false; + +  // Do not show the text +  showtext = false; +  recording = false; +  recording_prev = !recording; +  cprchanged = false; + +  muted = false; +  muted_prev = !muted; +} + +Player::~Player() +{ +  deinitSDL(); +  if(yuv_draw) delete yuv_draw; +} + +void Player::reinitSDL() +{ +  deinitSDL(); +  initSDL(); +} + +void Player::deinitSDL() +{ +  SDL_FreeYUVOverlay(overlay); +  SDL_Quit(); +} + +void Player::initSDL() +{ +  if(SDL_Init(SDL_INIT_VIDEO) < 0) { +    info->error("Unable to init SDL: %s.", SDL_GetError()); +    noErrors = false; +    printf("failed!\n"); +    return; +  } + +  screen = SDL_SetVideoMode(width,  +                            height,  +                            0, // 0 bpp means 'use current display depth'  +                            SDL_HWSURFACE |  +                            SDL_ANYFORMAT |  +                            SDL_HWACCEL ); + +  if(!screen) { +    info->error("Unable to set %dx%d video: %s.",  +            720, 576, SDL_GetError()); +    noErrors = false; +    printf("failed!\n"); +    return; +  } + +  overlay = SDL_CreateYUVOverlay(720, +                                 576, +                                 SDL_YUY2_OVERLAY, // Match for the libdv decoder output +                                 screen); +  if(!overlay) { +    info->error("Unable to create SDL overlay: %s.", SDL_GetError()); +    noErrors = false; +    printf("failed!\n"); +    return; +  } + +  // Setup the displayarea. +  rect.x = 0; +  rect.y = 0; +  rect.w = width; +  rect.h = height; + +  yuv_draw->setOverlay(overlay); +} + +void Player::player() +{ +  SDL_Event event; +  Frame *frame; + +  int pitches[3]; + +  if(!noErrors) return; // FIXME: Gracefully exit... + +  bool first = true; +	dv_decoder_t *decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE); +  decoder->quality = DV_QUALITY_BEST; + +  while(*running) { +    // Wait for the semaphore to be free... then run +    sem_wait(&play_sem); +    sem_post(&play_sem); + +    if(bypass) continue; + +    if(!SDL_WaitEvent(&event)) break; // FIXME: Gracefully exit...  + +    switch(event.type) { +    case SDL_KEYDOWN: +      switch(event.key.keysym.sym) { +      case SDLK_q: +      case SDLK_ESCAPE: +        goto quitit; +      default: +        break; +      } +      break; +       +    case SDL_USEREVENT: +      frame = queue->pop(); +      if(!frame) break; +       +      if(first) { +        pitches[0] = overlay->pitches[0]; +        pitches[1] = overlay->pitches[1]; +        pitches[2] = overlay->pitches[2]; + +        dv_parse_header(decoder, frame->data); +        //dv_parse_packs(decoder, frame->data); // Not needed anyway! + +        decoder->system = e_dv_system_625_50;  // PAL lines, PAL framerate +        decoder->sampling = e_dv_sample_422;  // 4 bytes y, 2 bytes u, 2 bytes v +        decoder->std = e_dv_std_iec_61834; +        decoder->num_dif_seqs = 12; +        first = false; +      } +       +      if(SDL_LockYUVOverlay(overlay) == -1) info->error("SDL_LockYUVOverlay failed."); + +      // libdv img decode to yuv +			dv_decode_full_frame(decoder,  +                           frame->data,  +                           e_dv_color_yuv,  +                           overlay->pixels, +                           pitches); + +      // Set status text +      //      if(muted != muted_prev) { +        yuv_draw->mute(muted); +        //        muted_prev = muted; +        //      } +      if(recording != recording_prev) { +        if(recording) yuv_draw->setTopText(TEXT_RECORDING); +        else yuv_draw->setTopText(TEXT_STOPPED); +        recording_prev = recording; +      } + +      // Draw overlaytext (if enabled) +      if(showtext) { +        if(cprchanged) { +          yuv_draw->setBottomText(cpr); +          cprchanged = false; +        } +        yuv_draw->draw(); +      } + +      SDL_UnlockYUVOverlay(overlay); +      SDL_DisplayYUVOverlay(overlay, &rect); +      delete frame; +      break; +       +    case SDL_QUIT: +    quitit: +      *running = 0; +      break; + +    default: +      break; +    } +  } +  if(decoder) dv_decoder_free(decoder); + +  struct timespec ts; + +  /* Remove any late buffer */ +  /* We don't care, the encoder finishes them all */ +  ts.tv_sec = 0; +  ts.tv_nsec = 100000000L;	// 100ms +  nanosleep(&ts, NULL); + +  frame = queue->pop(); +  if(frame) delete frame; +} + +void Player::thread_main() +{ +  player(); +  fprintf(stderr, "Player thread stopped.\n"); fflush(stderr); +} + +void Player::start() +{ +  sem_post(&play_sem); +} + +void Player::stop() +{ +  sem_wait(&play_sem); +} + +// FIXME: Worst case genario: the loop takes more than 1 second +//        to stop displaying => crash, due to deinitialization  +//        of SDL, while calling it.! +void Player::resize(int w, int h, bool s) +{ +  // Tell loop to stop +  bypass = true; + +  // Wait to ensure the current frame is done being displayed +  sleep(1); +   +  // Deinitialize SDL +  deinitSDL(); + +  // Set new size +  width = w; +  height = h; + +  // Initialize SDL +  initSDL(); + +  // Tell loop to go on. +  bypass = false; + +  showtext = s; +} + +void Player::setCpr(char *newcpr, char* name) +{ +  sprintf(cpr, "ID: %s  - %s", newcpr, name); +  cprchanged = true; +} + +void Player::startrecord() +{ +  recording = true; +} + +void Player::stoprecord() +{ +  recording = false; +} + +void Player::setMute(bool m) +{ +  muted = m; +} + +#endif /* USE_GUI */ diff --git a/client/player.h b/client/player.h new file mode 100644 index 0000000..0f5ca51 --- /dev/null +++ b/client/player.h @@ -0,0 +1,142 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            player.h + * + *  Fri Feb 25 20:23:19 CET 2005 + *  Copyright  2005 Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + * Originally from: + * RTVideoRec Realtime video recoder and encoder for Linux + * + * Copyright (C) 2004  Bent Bisballe + *  + */ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI + +#ifndef __RTVIDEOREC_PLAYER_H +#define __RTVIDEOREC_PLAYER_H + +#include "info.h" + +#include <stdio.h> +#include <stdlib.h> +#include <SDL/SDL.h> +//#include <avformat.h> + +#include "util.h" +#include "queue.h" + +#include "thread.h" +#include "frame.h" + +#include <qwidget.h> + +#include "yuv_draw.h" + +#define TEXT_RECORDING "Optager" +#define TEXT_STOPPED "Stoppet" + +//#define DISPLAYWIDTH	720	// FIXME: These numbers suck! +//#define DISPLAYHEIGHT	576 + +/** + * This class contains the SDL code, for displaying the movie frames + * in the widget, using hardware overlay. + */ +class Player : public Thread { +public: +  Player(Info *ginfo, +         int width, int height, +         volatile int *grunning, +         sem_t	*gsem, +         Queue<Frame> *gqueue, +         pthread_mutex_t *gmutex); +  ~Player(); + +  // These functions are used to set the overlay text. +  void setCpr(char *newcpr, char* name); +  void startrecord(); +  void stoprecord(); + +  // Start and stop runnning video (freeze/unfreeze) +  void start(); +  void stop(); + +  // Used to reinitialize the SDL output width a new size +  void resize(int width, int height, bool showtext); + +  void thread_main(); + +  void setMute(bool mute); + +private: + +  void initSDL(); +  void deinitSDL(); +  void reinitSDL(); + +  // Output dimensions (overlay) +  volatile int width; +  volatile int height; + +  SDL_Rect rect; + +  // Set to true, whenever a resize is requested. +  volatile bool bypass; + +  // Vars for the text overlay +  volatile bool showtext; +  volatile bool recording; +  bool recording_prev; + +  volatile bool muted; +  bool muted_prev; + +  volatile bool cprchanged; +  char cpr[256]; + +  Info *info; + +  void player(); + +  // Used to verify if errors ha ocurred previously. +  bool noErrors; + +  volatile int *running; +  sem_t	*sem; +  Queue<Frame> *queue; +  pthread_mutex_t *mutex; + +  sem_t	play_sem; + +  SDL_Surface *screen; +  SDL_Overlay *overlay; + +  YUVDraw *yuv_draw; +}; + +#endif/*__RTVIDEOREC_PLAYER_H*/ + +#endif /* USE_GUI */ diff --git a/client/videowidget.cc b/client/videowidget.cc new file mode 100644 index 0000000..61b5c8e --- /dev/null +++ b/client/videowidget.cc @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            videowidget.cc + * + *  Fri Sep  3 14:36:37 2004 + *  Copyright  2004  Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include <config.h> + +#ifdef USE_GUI +  +#include "videowidget.h" + +#include "miav_config.h" + +VideoWidget::VideoWidget(QWidget *p, Camera *c, QWidget* old) : QWidget(p, "") +{ +  camera = c; +  parent = p; + +  oldWindow = old; + +  // A welltested hack to force SDL to draw in the QWidget +  QString ids; +  setenv("SDL_WINDOWID", ids.setNum(winId()), 1); +} + +VideoWidget::~VideoWidget() +{ +} + +QPixmap VideoWidget::getScreenshot() +{  +  return QPixmap::grabWindow (winId()); +} + +static VideoWidget *fs = NULL; + +void VideoWidget::mouseReleaseEvent(QMouseEvent *event) +{ +  if(!parent) {    // We are a fullscreen window +    QString ids; +    setenv("SDL_WINDOWID", ids.setNum(oldWindow->winId()), 1); +    camera->resize(oldWindow->width(), oldWindow->height(), false); +    destroy(); +  } else {         // We are a nested window +    // first delete old instance (if any) +    if(fs) delete fs; +    fs = new VideoWidget(NULL, camera, this); +    fs->showFullScreen(); +    fs->setFixedWidth(config->readInt("pixel_width")); +    fs->setFixedHeight(config->readInt("pixel_height")); +    camera->resize(fs->width(), fs->height(), true); +  } +} + +#endif /* USE_GUI */ diff --git a/client/videowidget.h b/client/videowidget.h new file mode 100644 index 0000000..b9ac9d6 --- /dev/null +++ b/client/videowidget.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            videowidget.h + * + *  Fri Sep  3 14:36:46 2004 + *  Copyright  2004  Bent Bisballe + *  deva@aasimon.org + ****************************************************************************/ + +/* + *    This file is part of MIaV. + * + *    MIaV 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. + * + *    MIaV 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 MIaV; if not, write to the Free Software + *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +  +#ifndef __VIDEOWIDGET_H__ +#define __VIDEOWIDGET_H__ + +#include <qwidget.h> +#include <qpixmap.h> + +#include "camera.h" + +class VideoWidget : public QWidget { +Q_OBJECT +public: +  VideoWidget(QWidget *parent, Camera *camera, QWidget *old = NULL); +  ~VideoWidget(); +  QPixmap getScreenshot(); +  void mouseReleaseEvent(QMouseEvent *event); + +private: +  Camera *camera; + +  QWidget *parent; + +  // Reassign SDL to this when closing (if non-NULL) +  QWidget *oldWindow; +}; + +#endif /* __VIDEOWIDGET_H__ */ + +#endif /* USE_GUI */ diff --git a/client/yuv_draw.cc b/client/yuv_draw.cc new file mode 100644 index 0000000..21e5c28 --- /dev/null +++ b/client/yuv_draw.cc @@ -0,0 +1,241 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            yuv_draw.cc + * + *  Thu Sep 22 12:35:28 CEST 2005 + *  Copyright  2005 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of MIaV. + * + *  MIaV 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. + * + *  MIaV 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 MIaV; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +#include "yuv_draw.h" + +// for miav_app +#include "miav.h" + +#include <string.h> + +#define TEXT_MARGIN 10 + +#include "mainwindow.h" +static QImage *loadIcon( char *name, int height ) +{ +  QImage scaled; +  QImage *img; + +  img = new QImage(); +  img->load( name ); + +  int h = height; +  int w = (int)((float)img->width() / (float)(img->height() / (float)h)); + +  scaled = img->smoothScale(w, h); +  delete img; +  img = new QImage(scaled); + +  return img; +} + + +YUVDraw::YUVDraw() +{ +  overlay = NULL; + +  // One line of text! +  top_pixmap = new QPixmap(720 - TEXT_MARGIN, 20); +  bottom_pixmap = new QPixmap(720 - TEXT_MARGIN, 20); + +  for(int x = 0; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      top_grey[x][y] = 255; +    } +  } + +  for(int x = 0; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      bottom_grey[x][y] = 255; +    } +  } + +  img_muted = loadIcon(PIXMAP_MUTE, ICON_HEIGHT); +  img_unmuted = loadIcon(PIXMAP_UNMUTE, ICON_HEIGHT); +} + +YUVDraw::~YUVDraw() +{ +  delete top_pixmap; +  delete bottom_pixmap; +} + +void YUVDraw::setOverlay(SDL_Overlay* o) +{ +  overlay = o; +} + +void YUVDraw::addPixel(int x, int y, int val) +{ +  if(overlay->w < x) return; // Out of range +  if(overlay->h < y) return; // Out of range + +  Uint8 **pixels = overlay->pixels; +  Uint16 *pitches = overlay->pitches; + +  Uint8* pixel = &pixels[0][(2 * x) + (y * pitches[0])]; + +  if(val > 0) *pixel = (255<*pixel+val?255:*pixel+val); +  else *pixel = (0>*pixel+val?0:*pixel+val); +} + + +void YUVDraw::setTopText(char* text) +{ +  miav_app->lock(); +  top_pixmap->fill(); + +	QPainter painter; +	painter.begin(top_pixmap); +	painter.setFont( QFont( "Arial", 12, QFont::Bold ) ); +	painter.setPen( Qt::black ); +	painter.drawText(64, 15, text); +	painter.end(); + +  QImage image = top_pixmap->convertToImage(); + +  for(int x = 64; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      top_grey[x][y] = qGray(image.pixel(x, y)); +    } +  } +  miav_app->unlock(); +} + +void YUVDraw::setBottomText(char* text) +{ +  miav_app->lock(); +  bottom_pixmap->fill(); + +	QPainter painter; +	painter.begin(bottom_pixmap); +	painter.setFont( QFont( "Arial", 12, QFont::Bold ) ); +	painter.setPen( Qt::black ); +	painter.drawText(0, 15, text); +	painter.end(); + +  QImage image = bottom_pixmap->convertToImage(); + +  for(int x = 0; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      bottom_grey[x][y] = qGray(image.pixel(x, y)); +    } +  } +  miav_app->unlock(); +} + +void YUVDraw::draw() +{ +  for(int x = 0; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      if(top_grey[x][y] != 255) addPixel(x + TEXT_MARGIN, y + TEXT_MARGIN, 255 - top_grey[x][y]); +    } +  } + +  for(int x = 0; x < 720 - TEXT_MARGIN; x++) { +    for(int y = 0; y < 20; y++) { +      if(bottom_grey[x][y] != 255) addPixel(x + TEXT_MARGIN, (556 - TEXT_MARGIN)+ y, 255 - bottom_grey[x][y]); +    } +  } +} + +void YUVDraw::mute(bool muted) +{ +  int xoffset = 0; +  int yoffset = 0; + +  QImage *img; +  if(muted) img = img_muted; +  else img = img_unmuted; + +  //  Swicth the bool and draw an mute/unmute symbol +  float alpha, color; + +  for(int x = 0; x < ICON_WIDTH; x++) { +    for(int y = 0; y < ICON_HEIGHT; y++) { +      alpha = ((float)qAlpha(img->pixel(x, y)) / 255.0); +      color = (float)qGray(img->pixel(x, y)) * alpha; +      addPixel(x + xoffset, y + yoffset, (unsigned char)color); +    } +  } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/* +void YUVDraw::setText(int xoffset, int yoffset, char* text, int val) +{ +  for(unsigned int i = 0; i < strlen(text); i++) { +    for(int x = 0; x < FONT_WIDTH; x++) { +      for(int y = 0; y < FONT_HEIGHT; y++) { +        unsigned char col = palette[letter[(int)text[i]][y][x]]; +        if(col) col += val; +        addPixel(i * FONT_WIDTH + x + xoffset, y + yoffset, col); +      } +    } +  } +} +*/ + +/* +typedef struct{ +  Uint32 format; +  int w, h; +  int planes; +  Uint16 *pitches; +  Uint8 **pixels; +  Uint32 hw_overlay:1; +} SDL_Overlay; +*/ + +#endif/*USE_GUI*/ diff --git a/client/yuv_draw.h b/client/yuv_draw.h new file mode 100644 index 0000000..62f7d02 --- /dev/null +++ b/client/yuv_draw.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/*************************************************************************** + *            yuv_draw.h + * + *  Thu Sep 22 12:35:28 CEST 2005 + *  Copyright  2005 Bent Bisballe Nyeng + *  deva@aasimon.org + ****************************************************************************/ + +/* + *  This file is part of MIaV. + * + *  MIaV 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. + * + *  MIaV 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 MIaV; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA. + */ +#include "config.h" +#ifdef USE_GUI +#ifndef __MIAV_YUV_DRAW_H__ +#define __MIAV_YUV_DRAW_H__ + +#include <SDL/SDL.h> + +#include <qpixmap.h> +#include <qimage.h> +#include <qpainter.h> + +#define ICON_HEIGHT 48 +#define ICON_WIDTH 48 + +class YUVDraw { +public: +  YUVDraw(); +  ~YUVDraw(); + +  void setOverlay(SDL_Overlay* overlay); + +  void addPixel(int x, int y, int val); + +  void setTopText(char* text); +  void setBottomText(char* text); +  void mute(bool muted); + +  void draw(); + +private: +  SDL_Overlay* overlay; + +  QPixmap *top_pixmap; +  unsigned char top_grey[720][20]; + +  QPixmap *bottom_pixmap; +  unsigned char bottom_grey[720][20]; + +  QImage *img_muted; +  QImage *img_unmuted; +}; + +#endif/*__MIAV_YUV_DRAW_H__*/ +#endif/*USE_GUI*/ | 
