summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2006-03-04 14:53:17 +0000
committerdeva <deva>2006-03-04 14:53:17 +0000
commitf02095ee5ceb78f1781a9e250693b8866ca42181 (patch)
tree7953c6b5f004f31ee9b340d7cdff5e85890594fc
parent71c713dce2b5128862b293aa7fcc1d7ee89ffaf1 (diff)
*** empty log message ***
-rw-r--r--.in25
-rw-r--r--acinclude.m466
-rw-r--r--client/aboutwindow.cc92
-rw-r--r--client/aboutwindow.h83
-rw-r--r--client/camera.cc182
-rw-r--r--client/camera.h109
-rw-r--r--client/config.h33
-rw-r--r--client/cprlisten.cc106
-rw-r--r--client/cprlisten.h62
-rw-r--r--client/cprquerydialog.cc486
-rw-r--r--client/cprquerydialog.h170
-rw-r--r--client/debug.h103
-rw-r--r--client/decoder.cc286
-rw-r--r--client/decoder.h99
-rw-r--r--client/dv.h33
-rw-r--r--client/dv1394.cc175
-rw-r--r--client/dv1394.h55
-rw-r--r--client/encoder.cc273
-rw-r--r--client/encoder.h118
-rw-r--r--client/historywidget.cc77
-rw-r--r--client/historywidget.h52
-rw-r--r--client/info_gui.cc144
-rw-r--r--client/info_gui.h86
-rw-r--r--client/mainwindow.cc575
-rw-r--r--client/mainwindow.h193
-rw-r--r--client/messagebox.cc245
-rw-r--r--client/messagebox.h112
-rw-r--r--client/miav_client.cc60
-rw-r--r--client/miav_client.h42
-rw-r--r--client/player.cc322
-rw-r--r--client/player.h142
-rw-r--r--client/videowidget.cc76
-rw-r--r--client/videowidget.h57
-rw-r--r--client/yuv_draw.cc241
-rw-r--r--client/yuv_draw.h70
-rw-r--r--configure.in8
-rw-r--r--lib/aa_socket.cc254
-rw-r--r--lib/aa_socket.h42
-rw-r--r--lib/config.h33
-rw-r--r--lib/daemon.cc118
-rw-r--r--lib/daemon.h45
-rw-r--r--lib/file.cc240
-rw-r--r--lib/file.h84
-rw-r--r--lib/frame.cc52
-rw-r--r--lib/frame.h58
-rw-r--r--lib/frame_stream.h41
-rw-r--r--lib/info.cc68
-rw-r--r--lib/info.h61
-rw-r--r--lib/info_simple.cc94
-rw-r--r--lib/info_simple.h45
-rw-r--r--lib/jpeg_mem_dest.cc137
-rw-r--r--lib/jpeg_mem_dest.h39
-rw-r--r--lib/miav_config.cc492
-rw-r--r--lib/miav_config.h98
-rw-r--r--lib/mutex.cc48
-rw-r--r--lib/mutex.h45
-rw-r--r--lib/network.cc151
-rw-r--r--lib/network.h55
-rw-r--r--lib/package.h63
-rw-r--r--lib/queue.h248
-rw-r--r--lib/semaphore.cc48
-rw-r--r--lib/semaphore.h45
-rw-r--r--lib/socket.cc150
-rw-r--r--lib/socket.h61
-rw-r--r--lib/thread.cc56
-rw-r--r--lib/thread.h49
-rw-r--r--lib/threadsafe_queue.cc44
-rw-r--r--lib/threadsafe_queue.h58
-rw-r--r--lib/threadsafe_queue_fifo.cc70
-rw-r--r--lib/threadsafe_queue_fifo.h50
-rw-r--r--lib/threadsafe_queue_priority.cc101
-rw-r--r--lib/threadsafe_queue_priority.h64
-rw-r--r--lib/util.cc95
-rw-r--r--lib/util.h54
-rw-r--r--server/audio_encoder.cc218
-rw-r--r--server/audio_encoder.h60
-rw-r--r--server/config.h33
-rw-r--r--server/dvfile.cc60
-rw-r--r--server/dvfile.h51
-rw-r--r--server/img_encoder.cc196
-rw-r--r--server/img_encoder.h69
-rw-r--r--server/info_console.cc101
-rw-r--r--server/info_console.h53
-rw-r--r--server/iso11172-1.h161
-rw-r--r--server/iso11172-2.h73
-rw-r--r--server/iso11172-3.h85
-rw-r--r--server/libfame_wrapper.cc273
-rw-r--r--server/libfame_wrapper.h70
-rw-r--r--server/liblame_wrapper.cc293
-rw-r--r--server/liblame_wrapper.h71
-rw-r--r--server/libmplex_wrapper.cc485
-rw-r--r--server/libmplex_wrapper.h55
-rw-r--r--server/miav_daemon.cc108
-rw-r--r--server/miav_daemon.h42
-rw-r--r--server/miav_server.cc50
-rw-r--r--server/miav_server.h42
-rw-r--r--server/mov_encoder.cc293
-rw-r--r--server/mov_encoder.h83
-rw-r--r--server/mov_encoder_thread.cc158
-rw-r--r--server/mov_encoder_thread.h91
-rw-r--r--server/mov_encoder_writer.cc140
-rw-r--r--server/mov_encoder_writer.h73
-rw-r--r--server/multicast.cc178
-rw-r--r--server/multicast.h55
-rw-r--r--server/multicast_configuration.cc141
-rw-r--r--server/multicast_configuration.h56
-rw-r--r--server/multiplexer.cc495
-rw-r--r--server/multiplexer.h134
-rw-r--r--server/server.cc136
-rw-r--r--server/server.h37
-rw-r--r--server/server_status.cc77
-rw-r--r--server/server_status.h56
112 files changed, 13412 insertions, 54 deletions
diff --git a/.in b/.in
deleted file mode 100644
index eff77b6..0000000
--- a/.in
+++ /dev/null
@@ -1,25 +0,0 @@
-/* .in. Generated from configure.in by autoheader. */
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Version number of package */
-#undef VERSION
-
-/* Defined if on Win32 platform */
-#undef WIN32
diff --git a/acinclude.m4 b/acinclude.m4
index d5ef61f..b48ee93 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,4 +1,4 @@
-###############################################################################################################333
+##################################################################################################
# Check for Qt compiler flags, linker flags, and binary packages
AC_DEFUN([gw_CHECK_QT],
[
@@ -9,9 +9,9 @@ AC_MSG_CHECKING([QTDIR])
AC_ARG_WITH([qtdir], [ --with-qtdir=DIR Qt installation directory [default=$QTDIR]], QTDIR=$withval)
# Check that QTDIR is defined or that --with-qtdir given
if test x"$QTDIR" = x ; then
- QT_SEARCH="/usr/lib/qt31 /usr/local/qt31 /usr/lib/qt3 /usr/local/qt3 /usr/lib/qt2 /usr/local/qt2 /usr/lib/qt /usr/local/qt"
+ QT_SEARCH="/usr/lib/qt4 /usr/local/qt4 /usr/lib/qt /usr/local/qt"
for i in $QT_SEARCH; do
- if test -f $i/include/qglobal.h -a x$QTDIR = x; then QTDIR=$i; fi
+ if test -f $i/include/QtCore/QObject -a x$QTDIR = x; then QTDIR=$i; fi
done
fi
if test x"$QTDIR" = x ; then
@@ -27,13 +27,10 @@ QTDIR=`echo $QTDIR | perl -p -e 's/\\\\/\\//g'`
# Figure out which version of Qt we are using
AC_MSG_CHECKING([Qt version])
-QT_VER=`grep 'define.*QT_VERSION_STR\W' $QTDIR/include/qglobal.h | perl -p -e 's/\D//g'`
+QT_VER=`grep 'define.*QT_VERSION_STR\W' $QTDIR/include/QtCore/qglobal.h | perl -p -e 's/\D//g'`
case "${QT_VER}" in
- 2*)
- QT_MAJOR="2"
- ;;
- 3*)
- QT_MAJOR="3"
+ 4*)
+ QT_MAJOR="4"
;;
*)
AC_MSG_ERROR([*** Don't know how to handle this Qt major version])
@@ -41,26 +38,43 @@ case "${QT_VER}" in
esac
AC_MSG_RESULT([$QT_VER ($QT_MAJOR)])
-# Check that moc is in path
-AC_CHECK_PROG(MOC, moc, moc)
-if test x$MOC = x ; then
- AC_MSG_ERROR([*** moc must be in path])
-fi
-
-# uic is the Qt user interface compiler
-AC_CHECK_PROG(UIC, uic, uic)
-if test x$UIC = x ; then
- AC_MSG_ERROR([*** uic must be in path])
+if test x"$QTDIR" = x ; then
+ # Check that moc is in path
+ AC_CHECK_PROG(MOC, $QTDIR/bin/moc, $QTDIR/bin/moc)
+ if test x$MOC = x ; then
+ AC_MSG_ERROR([*** moc must be in path])
+ fi
+
+ # uic is the Qt user interface compiler
+ AC_CHECK_PROG(UIC, $QTDIR/bin/uic, $QTDIR/bin/uic)
+ if test x$UIC = x ; then
+ AC_MSG_ERROR([*** uic must be in path])
+ fi
+
+ # qembed is the Qt data embedding utility.
+ # It is located in $QTDIR/tools/qembed, and must be compiled and installed
+ # manually, we'll let it slide if it isn't present
+ AC_CHECK_PROG(QEMBED, qembed, qembed)
+else
+ # Check that moc is in path
+ MOC=$QTDIR/bin/moc
+
+ # uic is the Qt user interface compiler
+ UIC=$QTDIR/bin/uic
+
+ # qembed is the Qt data embedding utility.
+ # It is located in $QTDIR/tools/qembed, and must be compiled and installed
+ # manually, we'll let it slide if it isn't present
+ QEMBED=$QTDIR/bin/qembed
+
+ AC_SUBST(MOC)
+ AC_SUBST(UIC)
+ AC_SUBST(QEMBED)
fi
-# qembed is the Qt data embedding utility.
-# It is located in $QTDIR/tools/qembed, and must be compiled and installed
-# manually, we'll let it slide if it isn't present
-AC_CHECK_PROG(QEMBED, qembed, qembed)
-
# Calculate Qt include path
-QT_CXXFLAGS="-I$QTDIR/include"
+QT_CXXFLAGS="-I$QTDIR/include -I$QTDIR/include/Qt -I$QTDIR/include/Qt3Support -I$QTDIR/include/QtCore -I$QTDIR/include/QtDesigner -I$QTDIR/include/QtGui -I$QTDIR/include/QtNetwork -I$QTDIR/include/QtOpenGL -I$QTDIR/include/QtSql -I$QTDIR/include/QtXml"
QT_IS_EMBEDDED="no"
# On unix, figure out if we're doing a static or dynamic link
@@ -137,7 +151,7 @@ case "${host}" in
*linux*)
QT_LIBS="$QT_LIB"
if test $QT_IS_STATIC = yes && test $QT_IS_EMBEDDED = no; then
- QT_LIBS="$QT_LIBS -L$x_libraries -lXext -lX11 -lm -lSM -lICE -ldl -ljpeg"
+ QT_LIBS="$QT_LIBS -L$x_libraries -lQtCore -lQtGui -lXext -lX11 -lm -lSM -lICE -ldl -ljpeg"
fi
;;
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*/
diff --git a/configure.in b/configure.in
index 2d5721a..ec5bd62 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,6 @@
# Filename: configure.in
-AC_INIT(src/miav.cc)
-AM_INIT_AUTOMAKE( miav, 0.3.2 )
+AC_INIT(client/miav_client.cc)
+AM_INIT_AUTOMAKE( miav, 0.4.0 )
AC_PROG_CXX
@@ -126,7 +126,9 @@ AC_SUBST(LDFLAGS)
AC_OUTPUT(
Makefile
- src/Makefile
+ lib/Makefile
+ client/Makefile
+ server/Makefile
tools/Makefile
etc/Makefile
pixmaps/Makefile
diff --git a/lib/aa_socket.cc b/lib/aa_socket.cc
new file mode 100644
index 0000000..28ecead
--- /dev/null
+++ b/lib/aa_socket.cc
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+#include "aa_socket.h"
+
+//#include <string.h>
+
+#include <iostream>
+using namespace std;
+
+#include <unistd.h>
+//#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+
+#include <netinet/in.h>
+#if defined(linux)
+#include <endian.h>
+#else
+#include <sys/endian.h>
+#endif /*defined(linux)*/
+
+// for gethostbyname
+#include <netdb.h>
+
+// These functions are wrappers, to preserve my nice method naming!
+inline int _socket(int a,int b,int c){return socket(a,b,c);}
+inline int _connect(int a,const struct sockaddr *b,socklen_t c){return connect(a,b,c);}
+inline int _listen(int a,int b){return listen(a,b);}
+inline int _send(int a,char *b,unsigned int c, int d){return send(a,b,c,d);}
+
+
+AASocket::AASocket()
+{
+}
+
+AASocket::~AASocket()
+{
+ int err = close(socket); // close server
+ if(err == -1) throw Network_error("close", strerror(errno));
+}
+
+void AASocket::connect(char *host, unsigned short port)
+{
+ // create socket
+ socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ // PF_INET: ipv4, PF_INET6: ipv6
+ // tcp: IPPROTO_TCP
+ // upd: IPPROTO_UDP
+
+ if (socket == -1) throw Network_error("socket", strerror(errno));
+
+ socketaddr.sin_family = AF_INET; // Use "internet protocol" IP
+ socketaddr.sin_port = htons(port); // connect to that port
+ socketaddr.sin_addr.s_addr = INADDR_ANY;
+ // INADDR_ANY puts your IP address automatically
+
+
+
+ struct hostent *hp = gethostbyname(host);
+ // memcpy(&socketaddr.sin_addr.s_addr, *(hp->h_addr_list),sizeof(struct in_addr));
+ memcpy(&(socketaddr.sin_addr),*(hp->h_addr_list),sizeof(struct in_addr));
+
+ // FIXME: gethostbyname()
+ // socketaddr.sin_addr.s_addr = inet_addr(host);
+ //inet_aton (ip, &socketaddr.sin_addr);
+
+ int err = _connect(socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+ if(err == -1) throw Network_error("connect", strerror(errno));
+}
+
+void AASocket::listen(unsigned short port)
+{
+ int err;
+
+ bind_socket = _socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if(bind_socket == -1) throw Network_error("tmp socket", strerror(errno));
+
+ int optval = 1;
+ err = setsockopt(bind_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
+ if(err == -1) throw Network_error("setsockopt", strerror(errno));
+
+ socketaddr.sin_family = AF_INET; // Use "internet protocol" IP
+ socketaddr.sin_port = htons(port); // connect to that port
+ socketaddr.sin_addr.s_addr = INADDR_ANY;
+ // INADDR_ANY puts your IP address automatically
+
+ // bind socket to address specified by "sa" parameter
+ err = bind(bind_socket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+ if(err == -1) throw Network_error("bind", strerror(errno));
+
+ err = _listen(bind_socket, 5);
+ if(err == -1) throw Network_error("listen", strerror(errno));
+
+ int csalen = sizeof(socketaddr);
+ socket = accept(bind_socket,
+ (struct sockaddr*)&socketaddr,
+ (socklen_t*)&csalen);
+ if(socket == -1) throw Network_error("accept", strerror(errno));
+
+ err = close(bind_socket); // We don't need this anymore
+ bind_socket = -1;
+ if(err == -1) throw Network_error("tmp close", strerror(errno));
+}
+
+
+void AASocket::force_close()
+{
+ if(bind_socket != -1) close(bind_socket); // This should break the accept call
+}
+
+
+void AASocket::send(char* buf, unsigned int size)
+{
+ //unsigned int newsize = size + sizeof(unsigned int);
+ // char *newbuf = new char[newsize];
+
+ unsigned int nsize = htonl(size);
+ int n = _send(socket, (char*)&nsize, sizeof(unsigned int), MSG_WAITALL);
+ if(n == -1) throw Network_error("send", strerror(errno));
+
+ n = _send(socket, buf, size, MSG_WAITALL);
+ if(n == -1) throw Network_error("send", strerror(errno));
+}
+
+
+int AASocket::receive(char* buf, unsigned int size)
+{
+ unsigned int insize;
+
+ int n = recv(socket, &insize, sizeof(unsigned int), MSG_WAITALL);
+ if(n == -1) throw Network_error("recv", strerror(errno));
+
+ insize = ntohl(insize);
+ if(insize > size) {
+ char err_buf[256];
+ sprintf(err_buf, "Buffer is too small. Should be %d is %d." , insize, size);
+ throw Network_error("receive", err_buf);
+ }
+
+ n = recv(socket, buf, insize, MSG_WAITALL);
+ if(n == -1) throw Network_error("recv", strerror(errno));
+
+ return n;
+}
+
+
+void AASocket::send_string(string str)
+{
+ this->send((char*)str.c_str(), str.length());
+}
+
+
+string AASocket::receive_string()
+{
+ char buf[1024];
+ memset(buf, 0, sizeof(buf));
+
+ receive(buf, sizeof(buf));
+
+ return string(buf);
+}
+
+
+
+#ifdef TEST_SOCKET
+
+/**
+ * Test application for AASocket
+ * It should print the following to stdout:
+ * A: Hello, how are you?
+ * B: Fine thanks.
+ * A: What about you?
+ * B: I'm fine too.
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <string>
+#include <iostream>
+
+int main()
+{
+ char buf[1024];
+ memset(buf, 0, sizeof(buf));
+ int f = fork();
+ switch(f) {
+ case -1: // Fork error
+ perror("Fork failed!");
+ return 1;
+
+ case 0: // Forked child
+ {
+ try {
+ AASocket out;
+
+ sleep(1); // Make sure the other end is listening
+
+ // Test connect
+ out.connect("127.0.0.1", 6666);
+
+ // Test raw communication send
+ sprintf(buf, "Hello how are you?");
+ out.send(buf, sizeof(buf));
+
+ // Test raw communication receive
+ out.receive(buf, sizeof(buf));
+ std::cout << "B: " << buf << std::endl;
+
+ // Test string receive
+ std::string q = out.receive_string();
+ std::cout << "B: " << q << std::endl;
+
+ // Test string send
+ out.send_string(std::string("I'm fine too."));
+ return 0;
+ } catch(Network_error e) {
+ std::cerr << "Out: " << e.error << std::endl;
+ }
+ }
+ default: // Parent
+ {
+ try {
+ AASocket in;
+
+ // Test listen
+ in.listen(6666);
+
+ // Test raw communication receive
+ in.receive(buf, sizeof(buf));
+ std::cout << "A: " << buf << std::endl;
+
+ // Test raw communication send
+ sprintf(buf, "Fine thanks.");
+ in.send(buf, sizeof(buf));
+
+ // Test string send
+ in.send_string(std::string("What about you?"));
+
+ // Test string receive
+ std::string a = in.receive_string();
+ std::cout << "A: " << a << std::endl;
+ return 0;
+ } catch(Network_error e) {
+ std::cerr << "In: " << e.error << std::endl;
+ }
+ }
+ }
+ return 0;
+}
+#endif/*TEST_SOCKET*/
diff --git a/lib/aa_socket.h b/lib/aa_socket.h
new file mode 100644
index 0000000..0d02723
--- /dev/null
+++ b/lib/aa_socket.h
@@ -0,0 +1,42 @@
+#ifndef __SOCKET_H__
+#define __SOCKET_H__
+
+#include <string>
+
+#include <netinet/in.h>
+//#include <sys/socket.h>
+
+
+/**
+ * Exceptions
+ */
+struct Network_error {
+ Network_error(char *event, char *err) {
+ error = std::string(err) + " - in " + std::string(event);
+ }
+ std::string error;
+};
+
+class AASocket {
+public:
+ AASocket();
+ ~AASocket();
+
+ void listen(unsigned short port);
+ void connect(char *ip, unsigned short port);
+
+ void send(char* buf, unsigned int buf_size);
+ int receive(char* buf, unsigned int buf_size);
+
+ void send_string(std::string buf);
+ std::string receive_string();
+
+ void force_close();
+
+private:
+ struct sockaddr_in socketaddr;
+ int socket;
+ int bind_socket; // Tmp socket for listen.
+};
+
+#endif/*__SOCKET_H__*/
diff --git a/lib/config.h b/lib/config.h
new file mode 100644
index 0000000..e7101c9
--- /dev/null
+++ b/lib/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/lib/daemon.cc b/lib/daemon.cc
new file mode 100644
index 0000000..6e46bd5
--- /dev/null
+++ b/lib/daemon.cc
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.cc
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "daemon.h"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+
+// For getgrent and getgrent
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+
+// For strcmp
+#include <string.h>
+
+Daemon::Daemon()
+{}
+
+Daemon::~Daemon()
+{}
+
+int Daemon::run(const char *user, const char* group)
+{
+ int f;
+ int fd;
+
+ // Fetch user id
+ int uid = -1;
+ struct passwd *p = getpwent();
+ while(p) {
+ if(strcmp(p->pw_name, user) == 0) uid = p->pw_uid;
+ p = getpwent();
+ }
+ if(uid == -1) {
+ fprintf(stderr, "Could not find user \"%s\" in /etc/passwd file.\n", user);
+ }
+
+ // Fetch group id
+ int gid = -1;
+ struct group *g = getgrent();
+ while(g) {
+ if(strcmp(g->gr_name, group) == 0) gid = g->gr_gid;
+ g = getgrent();
+ }
+ if(gid == -1) {
+ fprintf(stderr, "Could not find group \"%s\" in /etc/group file.\n", group);
+ }
+
+ chdir("/");
+ umask(0);
+
+ f = fork();
+ switch(f) {
+ case -1: // Fork error
+ perror("Fork in daemon.cc");
+ return 1;
+
+ case 0: // Forked child
+ // Switch to given group
+ if(setgid(gid) != 0) {
+ fprintf(stderr, "Failed to change to group \"%s\" (gid: %d), quitting.\n", group, gid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current group\n");
+ }
+
+ // Switch to given user
+ if(setuid(uid) != 0) {
+ fprintf(stderr, "Failed to change to user \"%s\" (uid: %d), quitting.\n", user, uid);
+ perror("");
+ fprintf(stderr, "Runnning daemon as current user\n");
+ }
+
+ // Redirect stdin, stdout and stderr to /dev/null
+ fd = open("/dev/null", O_NOCTTY | O_RDWR, 0666);
+
+ dup2(0, fd);
+ dup2(1, fd);
+ dup2(2, fd);
+
+ setsid();
+
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGINT, SIG_IGN);
+ signal (SIGHUP, SIG_IGN);
+
+ return daemon_main();
+
+ default: // Parent
+ // exit(0);
+ return 0;
+ }
+}
diff --git a/lib/daemon.h b/lib/daemon.h
new file mode 100644
index 0000000..1bd663e
--- /dev/null
+++ b/lib/daemon.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * daemon.h
+ *
+ * Thu Jun 9 10:27:59 CEST 2005
+ * Copyright 2005 Bent Bisballe
+ * deva@aasimon.org
+ ****************************************************************************/
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __DAEMON_H__
+#define __DAEMON_H__
+
+#include <sys/types.h>
+
+class Daemon {
+public:
+ Daemon();
+ virtual ~Daemon();
+
+ /**
+ * Use NOBODY_GROUP and NOBODY_USER if no privileges are needed to run.
+ */
+ int run(const char* user, const char* group);
+
+private:
+ virtual int daemon_main() = 0;
+};
+
+#endif/*__DAEMON_H__*/
diff --git a/lib/file.cc b/lib/file.cc
new file mode 100644
index 0000000..3a59334
--- /dev/null
+++ b/lib/file.cc
@@ -0,0 +1,240 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * file.cc
+ *
+ * Thu Jun 9 15:31:38 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 "file.h"
+
+#include "miav_config.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <errno.h>
+
+// For ntoh*
+#include <netinet/in.h>
+
+#include <stdlib.h>
+
+File::File(char *fn, char* ext, Info *i)
+{
+ char path[256];
+
+ info = i;
+
+ savestate = SAVE;
+
+ filename = new char[strlen(fn) + 1];
+ extension = new char[strlen(ext) + 1];
+
+ strcpy(filename, fn);
+ strcpy(extension, ext);
+
+ num = 0;
+ seqnum = 0;
+ fd = -1;
+
+ int pos = (int)strrchr(filename, '/');
+ memset(path, 0, sizeof(path));
+
+ if(pos) { // pos is NULL, a file will be created in the current dir (Which is bad)
+ pos -= (int)filename; // Make pos relative to the beginning of the string
+ strncpy(path, filename, pos);
+ createPath(path);
+ }
+
+ Open();
+}
+
+File::~File()
+{
+ close(fd);
+
+ info->info("This session contains the following files...");
+ for(unsigned int cnt = 0; cnt < filelist.size(); cnt ++) {
+ info->info("[%s]", filelist[cnt].c_str());
+ }
+
+ std::string *trash = config->readString("server_trash");
+ std::string *later = config->readString("server_later");
+
+ switch(savestate) {
+ case NO_CHANGE:
+ info->warn("File had no savestate!");
+ break;
+
+ case SAVE:
+ info->info("Files in this session is to be saved.");
+ break;
+
+ case DELETE:
+ info->info("Files in this session is to be deleted (moved to trash).");
+ Move((char*)trash->c_str());
+ break;
+
+ case LATER:
+ info->info("Files in this session is stored for later decisson.");
+ Move((char*)later->c_str());
+ break;
+ }
+
+ delete filename;
+ delete extension;
+}
+
+int File::Move(char *destination)
+{
+ char newfile[256];
+ char filename[256];
+
+ createPath(destination);
+ for(unsigned int cnt = 0; cnt < filelist.size(); cnt ++) {
+ // TODO: Check is the file exists... if not make som noise!
+
+
+ // TODO: Move file filelist[cnt] to the destination folder.
+ strcpy(filename, (char*)filelist[cnt].c_str());
+ sprintf(newfile, "%s%s", destination, strrchr(filename, '/'));
+ if(rename((char*)filelist[cnt].c_str(), newfile) == -1)
+ info->error("Error moving file %s to %s:",
+ (char*)filelist[cnt].c_str(),
+ newfile,
+ strerror(errno));
+ }
+ return 0;
+}
+
+int File::Open()
+{
+ char fname[256];
+
+ if(fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+
+ while(fd == -1) {
+ if(seqnum) {
+ // A sequence number > 0
+ sprintf(fname, "%s%.3d-%d.%s", filename, num, seqnum, extension);
+ } else {
+ // A sequence number of 0
+ sprintf(fname, "%s%.3d.%s", filename, num, extension);
+ }
+ fd = open(fname, O_CREAT | O_WRONLY | O_ASYNC | O_EXCL, //| O_LARGEFILE
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if(fd == -1) num ++;
+
+ // If more than 100 files are created in one day, something is terribly wrong!
+ if(num > 100) {
+ info->error("Something is wrong with the path [%s]!", fname);
+ exit(1);
+ }
+
+ }
+
+ std::string filename_string(fname);
+ filelist.push_back(filename_string);
+
+ seqnum ++;
+
+ info->info("Output file: %s", fname);
+
+ return 0;
+}
+
+int File::Write(void* data, int size)
+{
+ int w;
+
+ w = write(fd, data, size);
+
+ if(w != size) {
+ info->info("Wrapping file.");
+ Open();
+ w = write(fd, data, size);
+ if(w != size) {
+ info->error("Out of diskspace!");
+ return -1;
+ }
+ }
+
+ return w;
+}
+
+int File::createPath(char* path)
+{
+ // struct stat stats;
+ char *subpath;
+
+ subpath = (char*)calloc(strlen(path) + 1, 1);
+
+ strcpy(subpath, path);
+
+ subpath[strrchr(subpath, '/') - subpath] = '\0';
+
+ if(strlen(subpath) > 0) createPath(subpath);
+
+ info->info("Checking and/or generating directory: %s", path);
+
+ // stat(path, &stats);
+ //if(!S_ISDIR(stats.st_mode) && S_ISREG(stats.st_mode))
+ mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH | S_IROTH);
+ // TODO: Check for creation errors!
+
+ free(subpath);
+
+ return 0;
+}
+
+void File::setSaveState(n_savestate s)
+{
+ savestate = s;
+ info->info("SETTING SAVESTATE TO: %d", savestate);
+}
+
+#ifdef __TEST_FILE
+#include "info_simple.h"
+
+int main(int argc, char *argv[]) {
+ if(argc < 3) {
+ fprintf(stderr, "usage:\n\ttest_file [filename] [extension]\n");
+ return 1;
+ }
+
+
+ InfoSimple info;
+ File file(argv[1], argv[2], &info);
+
+ unsigned int val = 0x01234567;
+ file.Write(val);
+
+}
+
+#endif/* __TEST_FILE*/
diff --git a/lib/file.h b/lib/file.h
new file mode 100644
index 0000000..04947df
--- /dev/null
+++ b/lib/file.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * file.h
+ *
+ * Thu Jun 9 15:31:38 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_FILE_H__
+#define __MIAV_FILE_H__
+
+#include "info.h"
+#include <stdio.h>
+
+#include <vector>
+#include <string>
+
+#include <string.h>
+
+// For savestate_n
+#include "package.h"
+
+class File {
+public:
+ File(char *filename, char* ext, Info* info);
+ ~File();
+
+ int Write(void* data, int size);
+ /*
+ int Write(char* data, int size);
+
+ int Write(unsigned long long int val);
+ int Write(long long int val);
+ int Write(long int val);
+ int Write(unsigned long int val);
+ int Write(int val);
+ int Write(unsigned int val);
+ int Write(short int val);
+ int Write(unsigned short int val);
+ */
+
+ void setSaveState(n_savestate savestate);
+
+private:
+ volatile n_savestate savestate;
+ Info* info;
+
+ std::vector<std::string> filelist;
+
+ int Open();
+
+ int Move(char *destination);
+
+ int fd;
+
+ int num;
+ int seqnum;
+
+ char* filename;
+ char* extension;
+
+ int createPath(char* path);
+};
+
+#endif/*__MIAV_FILE_H__*/
diff --git a/lib/frame.cc b/lib/frame.cc
new file mode 100644
index 0000000..a274d89
--- /dev/null
+++ b/lib/frame.cc
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * frame.cc
+ *
+ * Mon Nov 15 19:45:07 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>
+#include "frame.h"
+
+#include "debug.h"
+
+#include <memory.h>
+#include <stdlib.h>
+
+Frame::Frame(unsigned char *d, int sz)
+{
+ if(sz) data = new unsigned char[sz];
+ if(sz && d) memcpy(data, d, sz);
+ size = sz;
+ number = 0;
+ memset(timecode, 0, sizeof(timecode));
+
+ endOfFrameStream = false;
+}
+
+Frame::~Frame()
+{
+ delete data;
+ data = NULL;
+ size = 0;
+}
+
diff --git a/lib/frame.h b/lib/frame.h
new file mode 100644
index 0000000..988f460
--- /dev/null
+++ b/lib/frame.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * frame.h
+ *
+ * Mon Nov 15 19:45:07 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 __FRAME_H__
+#define __FRAME_H__
+
+// Definition of vector
+#include <vector>
+
+class Frame {
+public:
+ Frame(unsigned char *d, int sz);
+ ~Frame();
+
+ unsigned char *data;
+ unsigned int size;
+
+ unsigned int number;
+
+ unsigned int bitrate;
+
+ bool mute;
+
+ bool shoot;
+ int freeze; // 1 is freeze, -1 is unfreeze
+ bool record;
+ char timecode[12];
+
+ bool endOfFrameStream;
+};
+
+typedef std::vector< Frame* > FrameVector;
+
+#endif/*__FRAME_H__*/
diff --git a/lib/frame_stream.h b/lib/frame_stream.h
new file mode 100644
index 0000000..bc0b9a2
--- /dev/null
+++ b/lib/frame_stream.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * frame_stream.h
+ *
+ * Thu Jul 28 17:15:27 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_FRAME_STREAM_H__
+#define __MIAV_FRAME_STREAM_H__
+
+class frame_stream {
+public:
+ frame_stream() {}
+ virtual ~frame_stream() {}
+
+ virtual unsigned char *readFrame() = 0;
+};
+
+
+#endif/*__MIAV_FRAME_STREAM_H__*/
+
diff --git a/lib/info.cc b/lib/info.cc
new file mode 100644
index 0000000..701a705
--- /dev/null
+++ b/lib/info.cc
@@ -0,0 +1,68 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info.cc
+ *
+ * Mon Jun 13 22:16:18 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 "info.h"
+
+#include <time.h>
+
+Info::Info() {
+ pthread_mutex_init (&mutex, NULL);
+}
+
+void Info::log(char *fmt, ...)
+{
+ // const time_t t;
+ FILE *fp;
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ fp = fopen(log_filename.c_str(), "a");
+ if(!fp) {
+ fprintf(stderr, "Log file %s could not be opened in writemode.\n", log_filename.c_str());
+ return;
+ }
+
+ va_list argp;
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ time_t t = time(NULL);
+ char sdate[32];
+ memset(sdate, 0, sizeof(sdate));
+ strftime(sdate, sizeof(sdate), "%d %b %H:%M:%S", localtime(&t));
+
+ fprintf(fp, "%s miav[%d] %s\n", sdate, getpid(), buf);
+ // fprintf(stderr, "%s miav[%d] %s\n", sdate, getpid(), buf);
+
+ fclose(fp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+}
diff --git a/lib/info.h b/lib/info.h
new file mode 100644
index 0000000..d533051
--- /dev/null
+++ b/lib/info.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info.h
+ *
+ * Tue May 3 09:04:04 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_H__
+#define __MIAV_INFO_H__
+
+#include "miav_config.h"
+// Cyclic include :(
+class MiavConfig;
+
+#include <time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <string>
+using namespace std;
+
+class Info {
+public:
+ Info();
+ virtual ~Info() {}
+
+ virtual void error(char* fmt, ...) = 0;
+ virtual void warn(char* fmt, ...) = 0;
+ virtual void info(char* fmt, ...) = 0;
+ void log(char* fmt, ...);
+
+protected:
+ MiavConfig *config;
+
+ pthread_mutex_t mutex;
+ string log_filename;
+};
+
+#endif/*__MIAV_INFO_H__*/
diff --git a/lib/info_simple.cc b/lib/info_simple.cc
new file mode 100644
index 0000000..a3db393
--- /dev/null
+++ b/lib/info_simple.cc
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_simple.cc
+ *
+ * Tue Sep 20 17:00:25 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"
+#include "info_simple.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+InfoSimple::InfoSimple(): Info()
+{
+}
+
+InfoSimple::~InfoSimple()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void InfoSimple::error(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ fprintf(stderr, "Error: %s\n", buf);
+}
+
+void InfoSimple::warn(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ fprintf(stderr, "Warning: %s\n", buf);
+}
+
+void InfoSimple::info(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ fprintf(stderr, "Info: %s\n", buf);
+}
diff --git a/lib/info_simple.h b/lib/info_simple.h
new file mode 100644
index 0000000..302a371
--- /dev/null
+++ b/lib/info_simple.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_simple.h
+ *
+ * Tue Sep 20 17:00:25 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"
+#ifndef __MIAV_INFO_SIMPLE_H__
+#define __MIAV_INFO_SIMPLE_H__
+
+#include "info.h"
+
+class InfoSimple: public Info {
+public:
+ InfoSimple();
+ ~InfoSimple();
+
+ void error(char* fmt, ...);
+ void warn(char* fmt, ...);
+ void info(char* fmt, ...);
+
+private:
+};
+
+#endif/*__MIAV_INFO_SIMPLE_H__*/
diff --git a/lib/jpeg_mem_dest.cc b/lib/jpeg_mem_dest.cc
new file mode 100644
index 0000000..439c9a8
--- /dev/null
+++ b/lib/jpeg_mem_dest.cc
@@ -0,0 +1,137 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * jpeg_mem_dest.cc
+ *
+ * Thu Jul 28 16:40:08 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 "jpeg_mem_dest.h"
+
+#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently ?? size */
+
+/* Expanded data destination object for stdio output */
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+
+ JOCTET * outbuff; /* target buffer */
+ size_t * size;
+} mem_destination_mgr;
+
+typedef mem_destination_mgr * mem_dest_ptr;
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+void init_destination (j_compress_ptr cinfo)
+{
+ mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+
+ *dest->size = 0;
+ dest->pub.next_output_byte = dest->outbuff;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+}
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written. Usually needs to flush buffer.
+ *
+ * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
+ * application must deal with any cleanup that should happen even
+ * for error exit.
+ */
+void term_destination (j_compress_ptr cinfo)
+{
+ mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+ size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
+
+ /* Write any data remaining in the buffer */
+ if (datacount > 0) {
+ dest->outbuff+=datacount;
+ *dest->size+=datacount;
+ }
+}
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ *
+ * In typical applications, this should write the entire output buffer
+ * (ignoring the current state of next_output_byte & free_in_buffer),
+ * reset the pointer & count to the start of the buffer, and return TRUE
+ * indicating that the buffer has been dumped.
+ *
+ * In applications that need to be able to suspend compression due to output
+ * overrun, a FALSE return indicates that the buffer cannot be emptied now.
+ * In this situation, the compressor will return to its caller (possibly with
+ * an indication that it has not accepted all the supplied scanlines). The
+ * application should resume compression after it has made more room in the
+ * output buffer. Note that there are substantial restrictions on the use of
+ * suspension --- see the documentation.
+ *
+ * When suspending, the compressor will back up to a convenient restart point
+ * (typically the start of the current MCU). next_output_byte & free_in_buffer
+ * indicate where the restart point will be if the current call returns FALSE.
+ * Data beyond this point will be regenerated after resumption, so do not
+ * write it out when emptying the buffer externally.
+ */
+boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+ mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
+
+ dest->outbuff+=OUTPUT_BUF_SIZE;
+ *dest->size+=OUTPUT_BUF_SIZE;
+
+ dest->pub.next_output_byte = dest->outbuff;
+ dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
+
+ return TRUE;
+}
+
+/*
+ * Prepare for output to a memory buffer.
+ . The caller must have already allocated the buffer, and is responsible
+ * for closing it after finishing compression.
+ */
+void jpeg_mem_dest (j_compress_ptr cinfo, char * outbuff, size_t * size)
+{
+ mem_dest_ptr dest;
+
+ /* The destination object is made permanent so that multiple JPEG images
+ * can be written to the same file without re-executing jpeg_stdio_dest.
+ * This makes it dangerous to use this manager and a different destination
+ * manager serially with the same JPEG object, because their private object
+ * sizes may be different. Caveat programmer.
+ */
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
+ sizeof(mem_destination_mgr));
+ }
+
+ dest = (mem_dest_ptr) cinfo->dest;
+ dest->pub.init_destination = init_destination;
+ dest->pub.empty_output_buffer = empty_output_buffer;
+ dest->pub.term_destination = term_destination;
+ dest->outbuff = (JOCTET *)outbuff;
+ dest->size = (size_t *)size;
+}
diff --git a/lib/jpeg_mem_dest.h b/lib/jpeg_mem_dest.h
new file mode 100644
index 0000000..b1ff103
--- /dev/null
+++ b/lib/jpeg_mem_dest.h
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * jpeg_mem_dest.h
+ *
+ * Thu Jul 28 16:40:08 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_JPEG_MEM_DEST_H__
+#define __MIAV_JPEG_MEM_DEST_H__
+
+#include <stdio.h>
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+void jpeg_mem_dest (j_compress_ptr cinfo, char * outbuff, size_t * size);
+
+#endif/*__MIAV_JPEG_MEM_DEST_H__*/
diff --git a/lib/miav_config.cc b/lib/miav_config.cc
new file mode 100644
index 0000000..adfa5c5
--- /dev/null
+++ b/lib/miav_config.cc
@@ -0,0 +1,492 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_config.cc
+ *
+ * Sat Feb 19 14:13: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>
+#include "miav_config.h"
+
+MiavConfig *config;
+
+MiavConfig::MiavConfig(char *file, Info *i)
+{
+ info = i;
+ configs = NULL;
+
+ filename = string(file);
+
+ // Read config file
+ FILE* fp = fopen(file, "r");
+
+ if(!fp) {
+ if(info) info->error("Error reading configuration file %s\n", file);
+ else fprintf(stderr, "Error reading configuration file %s\n", file);
+ return;
+ }
+ fseek(fp, 0, SEEK_END);
+ int fsz = ftell(fp) + 1;
+ fseek(fp, 0, SEEK_SET);
+
+ char *raw = (char*)calloc(fsz, 1);
+ fread(raw, 1, fsz, fp);
+
+ fclose(fp);
+
+ configs = parse(raw);
+
+ free(raw);
+}
+
+MiavConfig::~MiavConfig()
+{
+ _cfg *die = NULL;
+ _cfg *cfg = configs;
+
+ while(cfg) {
+ if(die) free(die);
+ die = cfg;
+ cfg = cfg->next;
+ }
+ if(die) free(die);
+}
+
+/**
+ * Prints a reasonable error message when a parse error occurres.
+ */
+void MiavConfig::parseError(char* msg, _cfg* cfg)
+{
+ if(info) info->error("Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
+ else fprintf(stderr, "Error parsing file %s at line %d:\n\t%s\n\t%s\n",
+ filename.c_str(),
+ cfg->line,
+ cfg->orig,
+ msg);
+}
+
+_cfg* MiavConfig::readLines(char* raw)
+{
+ int line = 1;
+
+ _cfg *first = (_cfg*)calloc(1, sizeof(_cfg));
+ _cfg *current = first;
+ _cfg *next = NULL;
+
+ char *nl = strchr(raw, '\n');
+
+ while(nl != NULL) {
+ int len = nl - raw;
+
+ current->line = line;
+
+ current->orig = (char*) calloc(len + 1, 1);
+ strncpy(current->orig, raw, len);
+
+ // Find next newline
+ raw = nl+1;
+ nl = strchr(raw, '\n');
+
+ line++;
+
+ // Add _cfg
+ if(nl != NULL) {
+ next = (_cfg*)calloc(1, sizeof(_cfg));
+ current->next = next;
+ current = next;
+ } else {
+ current->next = NULL;
+ }
+ }
+
+ return first;
+}
+
+_cfg* MiavConfig::parseLines(_cfg *cfg)
+{
+ if(cfg == NULL) return NULL;
+
+ char *l = cfg->left = (char*)calloc(1, strlen(cfg->orig));
+ char *r = cfg->right = (char*)calloc(1, strlen(cfg->orig));
+
+ char *p = cfg->orig;
+
+ // Skip leftmost whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Empty line, with whitespaces
+ if(p == cfg->orig + strlen(cfg->orig)) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Parse left side
+ while(p < cfg->orig + strlen(cfg->orig) && !strchr("\t ", *p)) {
+ if(strchr("#", *p)) {
+ if(l != cfg->left) parseError("Incomplete line.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(strchr("=", *p)) break;
+
+ if(strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_", *p)) {
+ *l = *p;
+ l++;
+ } else {
+ char buf[256];
+ sprintf(buf, "Invalid left hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ p++;
+ }
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ if(*p != '=') {
+ parseError("Expected '='.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+ p++; // Get past the '='
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Parse right hand side
+ int instring = 0;
+ while(p < cfg->orig + strlen(cfg->orig) && !(strchr("\t ", *p) && instring != 1)) {
+ if(*p == '\"') instring++;
+ if(instring > 2) {
+ parseError("Too many '\"'.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ if(instring == 1) {
+ // Accept all chars
+ *r= *p;
+ r++;
+ } else {
+ // Accept only those chars valid for the data types.
+ if(strchr("truefalseyesnoTRUEFALSEYESNO1234567890\",.-", *p)) {
+ if(*p == ',') *r= '.';
+ *r = *p;
+ r++;
+ } else if(!strchr("\n", *p)) {
+ char buf[256];
+ sprintf(buf, "Invalid right hand side character at [%s].", p);
+ parseError(buf, cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+ if(*p == '#') break;
+ }
+
+ p++;
+ }
+
+ // Skip whitespace
+ while(p < cfg->orig + strlen(cfg->orig) && strchr("\t ", *p)) {
+ p++;
+ }
+
+ // Detect if whitespace ocurred inside righthand value.
+ if(p != cfg->orig + strlen(cfg->orig)) {
+ parseError("Invalid use of whitespace.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for instring (string not ended)
+ if(instring == 1) {
+ parseError("String not closed.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty line
+ if(l == cfg->left && r == cfg->right) {
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty left side.
+ if(l == cfg->left) {
+ parseError("Empty left side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ // Check for empty right side.
+ if(r == cfg->right) {
+ parseError("Empty right side.", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return parseLines(next);
+ }
+
+ cfg->next = parseLines(cfg->next);
+ return cfg;
+}
+
+
+_cfg *MiavConfig::createSemantics(_cfg *cfg) {
+ if(cfg == NULL) return NULL;
+
+ cfg->type = CONFIG_UNKNOWN;
+
+ // Boolean - true
+ if(strcasecmp(cfg->right, "yes") == 0 ||
+ strcasecmp(cfg->right, "true") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = true;
+ }
+
+ // Boolean - false
+ if(strcasecmp(cfg->right, "no") == 0 ||
+ strcasecmp(cfg->right, "false") == 0) {
+ cfg->type = CONFIG_BOOL;
+ cfg->boolval = false;
+ }
+
+ // String
+ if(cfg->right[0] == '\"') {
+ cfg->type = CONFIG_STRING;
+ cfg->right[strlen(cfg->right) - 1] = '\0';
+ cfg->stringval = new string(cfg->right + 1);
+
+ }
+
+ // Number
+ bool number = true;
+ char *p = cfg->right;
+ while(p < cfg->right + strlen(cfg->right)) {
+ if(!strchr("01234567890.-", *p)) number = false;
+ p++;
+ }
+
+ // Integer
+ if(number && strstr(cfg->right, ".") == NULL ) {
+ cfg->type = CONFIG_INT;
+ cfg->intval = atoi(cfg->right);
+ }
+
+ // Float
+ if(number && strstr(cfg->right, ".") != NULL) {
+ cfg->type = CONFIG_FLOAT;
+ cfg->floatval = atof(cfg->right);
+ }
+
+ if(cfg->type == CONFIG_UNKNOWN) {
+ parseError("Unknown type (see 'man miav.conf' for valid right hand sides).", cfg);
+ _cfg* next = cfg->next;
+ free(cfg->orig);
+ free(cfg->left);
+ free(cfg->right);
+ free(cfg);
+ return createSemantics(next);
+ }
+
+ // Create name
+ cfg->name = new string(cfg->left);
+
+ cfg->next = createSemantics(cfg->next);
+ return cfg;
+}
+
+
+_cfg* MiavConfig::parse(char* raw)
+{
+ _cfg *first = readLines(raw);
+ first = parseLines(first);
+
+ first = createSemantics(first);
+
+ /*
+ _cfg* cfg = first;
+ while(cfg) {
+ printf("Node:\n");
+ printf("\tLine: [%d]\n", cfg->line);
+ printf("\tOrig: [%s]\n", cfg->orig);
+ printf("\tLeft: [%s]\n", cfg->left);
+ printf("\tRight: [%s]\n", cfg->right);
+
+ switch(cfg->type) {
+ case CONFIG_INT:
+ printf("\tInt value: %d\n", cfg->intval);
+ break;
+ case CONFIG_BOOL:
+ printf("\tBool value: %d\n", cfg->boolval);
+ break;
+ case CONFIG_FLOAT:
+ printf("\tFloat value: %f\n", cfg->floatval);
+ break;
+ case CONFIG_STRING:
+ printf("\tString value: %s\n", cfg->stringval->c_str());
+ break;
+ case CONFIG_UNKNOWN:
+ printf("\tUnknown type: %s\n", cfg->right);
+ break;
+ }
+
+ cfg= cfg->next;
+ }
+ */
+ return first;
+}
+
+int MiavConfig::readInt(char *node)
+{
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_INT) return n->intval;
+ parseError("Expected integer.", n);
+ }
+ return 0;
+}
+
+bool MiavConfig::readBool(char *node)
+{
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_BOOL) return n->boolval;
+ if(n->type == CONFIG_INT) return (n->intval != 0);
+ parseError("Expected boolean.", n);
+ }
+ return false;
+}
+
+string *MiavConfig::readString(char *node)
+{
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_STRING) return n->stringval;
+ parseError("Expected string.", n);
+ }
+ return &emptyString;
+}
+
+float MiavConfig::readFloat(char *node)
+{
+ _cfg* n = findNode(node);
+ if(n) {
+ if(n->type == CONFIG_FLOAT) return n->floatval;
+ if(n->type == CONFIG_INT) return (float)n->intval;
+ parseError("Expected float.", n);
+ }
+ return 0.0f;
+}
+
+_cfg *MiavConfig::findNode(char* node)
+{
+ _cfg *cfg = configs;
+
+ while(cfg) {
+ if(!strcmp(node, cfg->name->c_str())) return cfg;
+ cfg = cfg->next;
+ }
+ if(info) info->error("Missing line in configuration file: \"%s\"!\n", node);
+ else fprintf(stderr, "Missing line in configuration file: \"%s\"!\n", node);
+
+ return NULL;
+}
+
+#ifdef __TEST_MIAV_CONFIG
+
+int main(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "usage:\n\tmiav_config [filename]\n");
+ return 1;
+ }
+
+ MiavConfig cfg(argv[1]);
+ printf("Server user: [%s]\n", cfg.readString("server_user")->c_str());
+ printf("Resolution: [%f]\n", cfg.readFloat("screensize"));
+ printf("Resolution (as int): [%d]\n", cfg.readInt("screensize"));
+ printf("Width: [%d]\n", cfg.readInt("pixel_width"));
+ printf("Width (as float): [%f]\n", cfg.readFloat("pixel_width"));
+ printf("Frame quality: [%d]\n", cfg.readInt("frame_quality"));
+ printf("Skip frames: [%d]\n", cfg.readBool("player_skip_frames"));
+ printf("Skip frames (as int): [%d]\n", cfg.readInt("player_skip_frames"));
+ printf("Frame quality (as bool): [%d]\n", cfg.readBool("frame_quality"));
+
+}
+
+#endif/* __TEST_MIAV_CONFIG*/
diff --git a/lib/miav_config.h b/lib/miav_config.h
new file mode 100644
index 0000000..a8658f1
--- /dev/null
+++ b/lib/miav_config.h
@@ -0,0 +1,98 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_config.h
+ *
+ * Sat Feb 19 14:13: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"
+#ifndef __MIAV_MIAV_CONFIG_H__
+#define __MIAV_MIAV_CONFIG_H__
+
+#include <string>
+using namespace std;
+
+#include "info.h"
+// Cyclic include :(
+class Info;
+
+typedef enum {
+ CONFIG_UNKNOWN,
+ CONFIG_INT,
+ CONFIG_BOOL,
+ CONFIG_FLOAT,
+ CONFIG_STRING
+} ConfigType;
+
+
+typedef struct __cfg {
+ // For parsing
+ char* orig;
+ int line;
+ char* left;
+ char* right;
+
+ // For traversal
+ string *name;
+ ConfigType type;
+ int intval;
+ bool boolval;
+ float floatval;
+ string *stringval;
+
+ struct __cfg* next;
+} _cfg;
+
+class MiavConfig {
+public:
+ MiavConfig(char *file, Info *info = NULL);
+ ~MiavConfig();
+
+ int readInt(char *node);
+ bool readBool(char *node);
+ string *readString(char *node);
+ float readFloat(char *node);
+
+protected:
+ Info *info;
+ string filename;
+
+ _cfg *createSemantics(_cfg *cfg);
+ _cfg* readLines(char* raw);
+ _cfg* parseLines(_cfg *cfg);
+ _cfg *parse(char* raw);
+ string emptyString;
+
+
+#if 0
+ _cfg *addConfig(_cfg *parent, char* conf);
+ char *strip(char* conf);
+#endif
+
+ void parseError(char* msg, _cfg *cfg);
+ _cfg *findNode(char* node);
+ _cfg *configs;
+};
+
+extern MiavConfig *config;
+
+#endif/*__MIAV_MIAV_CONFIG_H__*/
diff --git a/lib/mutex.cc b/lib/mutex.cc
new file mode 100644
index 0000000..483d71a
--- /dev/null
+++ b/lib/mutex.cc
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mutex.cc
+ *
+ * Sat Oct 8 17:44:09 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"
+#include "mutex.h"
+
+Mutex::Mutex()
+{
+ pthread_mutex_init (&mutex, NULL);
+}
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void Mutex::lock()
+{
+ pthread_mutex_lock( &mutex );
+}
+
+void Mutex::unlock()
+{
+ pthread_mutex_unlock( &mutex );
+}
diff --git a/lib/mutex.h b/lib/mutex.h
new file mode 100644
index 0000000..0b1f4e7
--- /dev/null
+++ b/lib/mutex.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mutex.h
+ *
+ * Sat Oct 8 17:44:09 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"
+#ifndef __MIAV_MUTEX_H__
+#define __MIAV_MUTEX_H__
+
+#include <pthread.h>
+
+class Mutex {
+public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+
+private:
+ pthread_mutex_t mutex;
+};
+
+#endif/*__MIAV_MUTEX_H__*/
diff --git a/lib/network.cc b/lib/network.cc
new file mode 100644
index 0000000..799bc98
--- /dev/null
+++ b/lib/network.cc
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * network.cc
+ *
+ * Wed Nov 3 21:23:14 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>
+#include "network.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+
+Network::Network(Socket *gs, Info *ginfo)
+{
+ info = ginfo;
+ s = gs;
+}
+
+Network::~Network()
+{
+}
+
+int Network::write(void *buf, int size)
+{
+ if(!s->isConnected()) {
+ // info->error("Write attempted to a socket not connected!");
+ return -1;
+ }
+ int n = send(s->ssocket, buf, size, MSG_WAITALL);
+
+ if(n == -1) {
+ info->error("An error occurred!");
+ }
+
+ return n;
+}
+
+int Network::read(void *buf, int size)
+{
+ if(!s->isConnected()) {
+ // info->error("Read attempted from a socket not connected!");
+ return -1;
+ }
+ int n = recv(s->ssocket, buf, size, MSG_WAITALL);
+
+ if(n == -1) {
+ info->error("An error occurred!");
+ }
+
+ return n;
+}
+
+/*
+struct msghdr {
+ void *msg_name // Optional address.
+ socklen_t msg_namelen // Size of address.
+ struct iovec *msg_iov // Scatter/gather array.
+ int msg_iovlen // Members in msg_iov.
+ void *msg_control // Ancillary data; see below.
+ socklen_t msg_controllen // Ancillary data buffer len.
+ int msg_flags // Flags on received message.
+};
+*/
+
+int Network::sendPackage(n_header *h, void* buf, int bufsz)
+{
+ struct msghdr msg;
+ struct iovec iovecs[2];
+
+ if(!s->isConnected()) {
+ // info->error("Write attempted to a socket not connected!");
+ return -1;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_iov = iovecs;
+ msg.msg_iovlen = 2;
+
+ msg.msg_iov[0].iov_base = h;
+ msg.msg_iov[0].iov_len = sizeof(*h);
+
+ msg.msg_iov[1].iov_base = buf;
+ msg.msg_iov[1].iov_len = bufsz;
+
+ int n = sendmsg(s->ssocket, &msg, 0);
+ if(n < 0) {
+ info->error("A network error ocurred during sendPackage!");
+ return -1;
+ }
+
+ return n;
+}
+
+int Network::recvPackage(n_header *h, void* buf, int bufsz)
+{
+ struct msghdr msg;
+ struct iovec iovecs[2];
+
+ if(!s->isConnected()) {
+ // info->error("Read attempted to a socket not connected!");
+ return -1;
+ }
+
+ memset(&msg, 0, sizeof(msg));
+
+ iovecs[0].iov_base = h;
+ iovecs[0].iov_len = sizeof(*h);
+
+ iovecs[1].iov_base = buf;
+ iovecs[1].iov_len = bufsz;
+
+ msg.msg_iov = iovecs;
+ msg.msg_iovlen = 2;
+
+ int n = recvmsg(s->ssocket, &msg, MSG_WAITALL);
+
+ if(n < 0) {
+ info->error("A network error ocurred during recvPackage!");
+ return -1;
+ }
+
+ if(msg.msg_iovlen != 2) {
+ info->error("Wrong package format!");
+ return -1;
+ }
+ return n;
+}
+
diff --git a/lib/network.h b/lib/network.h
new file mode 100644
index 0000000..f64310e
--- /dev/null
+++ b/lib/network.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * network.h
+ *
+ * Wed Nov 3 21:23:14 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 __MIAVLIB_NETWORK_H__
+#define __MIAVLIB_NETWORK_H__
+
+#include "socket.h"
+#include "package.h"
+#include "info.h"
+
+class Network {
+public:
+ Network(Socket *gs, Info* ginfo);
+ ~Network();
+
+ // Raw communication
+ int write(void *buf, int size);
+ int read(void *buf, int size);
+
+ // Package communication
+ int sendPackage(n_header *h, void* buf, int bufsz);
+ int recvPackage(n_header *h, void* buf, int bufsz);
+
+private:
+ Info *info;
+ Socket *s;
+};
+
+#endif/*__NETWORK_H__*/
+
+
diff --git a/lib/package.h b/lib/package.h
new file mode 100644
index 0000000..a16557a
--- /dev/null
+++ b/lib/package.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * package.h
+ *
+ * Tue Nov 9 10:57:20 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 __MIAVLIB_PACKAGE_H__
+#define __MIAVLIB_PACKAGE_H__
+
+typedef enum {
+ NO_CHANGE = 0,
+ SAVE,
+ DELETE,
+ LATER
+} n_savestate;
+
+typedef enum {
+ DATA_HEADER = 0x0001,
+ INFO_HEADER = 0x0002
+} n_header_type;
+
+typedef struct {
+ n_header_type header_type;
+ union {
+ struct {
+ char cpr[32]; // Can hold wierd cpr numbers as well (not only danish)
+ bool record;
+ bool freeze;
+ bool snapshot;
+ n_savestate savestate;
+ bool mute;
+ } h_data;
+ struct {
+ int fisk;
+ } h_info;
+ } header;
+} n_header;
+
+
+#endif/*__PACKAGE_H__*/
+
+
diff --git a/lib/queue.h b/lib/queue.h
new file mode 100644
index 0000000..3cb6fbc
--- /dev/null
+++ b/lib/queue.h
@@ -0,0 +1,248 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * queue.h
+ *
+ * Tue Nov 9 10:57:20 CET 2004
+ * Copyright 2004 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"
+#ifndef __RTVIDEOREC_QUEUE_H
+#define __RTVIDEOREC_QUEUE_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+//#include <avformat.h>
+//#include <avcodec.h>
+
+#include "thread.h"
+#include "util.h"
+
+typedef struct __buf_t {
+ struct __buf_t *next;
+ struct __buf_t *prev;
+ void *data;
+} buf_t;
+
+
+template<typename T>
+class Queue {
+public:
+ Queue(int glimit = 0);
+ ~Queue();
+
+ void push(T *t);
+ T *pop();
+ T *peek();
+
+ void lock();
+ void unlock();
+
+ int length();
+
+private:
+ volatile bool locked;
+ int limit;
+ buf_t *head;
+ buf_t *tail;
+ int count;
+ pthread_mutex_t mutex;
+ T *_pop();
+};
+
+/**
+ * Initialize queue
+ */
+template<typename T>
+Queue<T>::Queue(int glimit)
+{
+ locked = false;
+ pthread_mutex_init (&mutex, NULL);
+ limit = glimit;
+ count = 0;
+ head = NULL;
+ tail = NULL;
+}
+
+/**
+ * Clean up queue.
+ */
+template<typename T>
+Queue<T>::~Queue()
+{
+ if(count != 0) {
+ fprintf(stderr, "Queue not empty (%d)\n", count);
+ while(T *t = _pop()) delete t;
+ }
+ pthread_mutex_destroy(&mutex);
+}
+
+/**
+ * Push element on queue.
+ */
+template<typename T>
+void Queue<T>::push(T *t)
+{
+ if(locked) {
+ delete t;
+ return;
+ }
+
+ pthread_mutex_lock(&mutex);
+
+ buf_t *b = (buf_t*)xmalloc(sizeof(*b));
+ b->data = (void*)t;
+
+ assert(b != NULL);
+
+ if(limit && count > 0) {
+ T* tmp = (T*)_pop();
+ delete tmp;
+ }
+
+ if(!head) {
+ head = tail = b;
+ b->next = b->prev = NULL;
+ count = 1;
+ pthread_mutex_unlock(&mutex);
+ return;
+ }
+
+ b->next = tail;
+ b->prev = NULL;
+ if(tail)
+ tail->prev = b;
+ tail = b;
+ count++;
+
+ pthread_mutex_unlock(&mutex);
+}
+
+/**
+ * Pop element from queue.
+ * If queue is empty, NULL is returned.
+ */
+template<typename T>
+T *Queue<T>::pop()
+{
+ pthread_mutex_lock(&mutex);
+ T *d = _pop();
+ pthread_mutex_unlock(&mutex);
+ return d;
+}
+
+/**
+ * Pop helper method
+ * If queue is empty, NULL is returned.
+ */
+template<typename T>
+T *Queue<T>::_pop()
+{
+ T *d;
+ buf_t *b;
+
+ assert(count >= 0);
+
+ if(count == 0) {
+ return NULL;
+ }
+
+ b = head;
+ if(b->prev)
+ b->prev->next = NULL;
+ head = b->prev;
+ if(b == tail)
+ tail = NULL;
+ count--;
+
+ d = (T*)b->data;
+ free(b);
+
+ return d;
+}
+
+/**
+ * Peek foremost element in queue
+ * If queue is empty, NULL is returned.
+ */
+template<typename T>
+T *Queue<T>::peek()
+{
+ // pthread_mutex_lock(&mutex);
+ T *d;
+
+ // assert(count >= 0);
+
+ if(count == 0) {
+ return NULL;
+ }
+
+ d = (T*)head->data;
+ // pthread_mutex_unlock(&mutex);
+ return d;
+}
+
+/**
+ * Print current length of queue
+ */
+template<typename T>
+int Queue<T>::length()
+{
+ int length;
+ pthread_mutex_lock(&mutex);
+ length = count;
+ pthread_mutex_unlock(&mutex);
+ return length;
+}
+
+/**
+ * Lock the queue (all elements pushed from this point will be deleted.)
+ */
+template<typename T>
+void Queue<T>::lock()
+{
+ fprintf(stderr, "Lock this motherfucker..."); fflush(stderr);
+ locked = true;
+ fprintf(stderr, "done\n"); fflush(stderr);
+}
+
+/**
+ * Unlock the queue.
+ */
+template<typename T>
+void Queue<T>::unlock()
+{
+ fprintf(stderr, "Unlock this motherfucker..."); fflush(stderr);
+ locked = false;
+ fprintf(stderr, "done\n"); fflush(stderr);
+}
+
+#endif
+
diff --git a/lib/semaphore.cc b/lib/semaphore.cc
new file mode 100644
index 0000000..147bd24
--- /dev/null
+++ b/lib/semaphore.cc
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * semaphore.cc
+ *
+ * Sat Oct 8 17:44:13 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"
+#include "semaphore.h"
+
+Semaphore::Semaphore()
+{
+ sem_init(&semaphore, 0, 0);
+}
+
+Semaphore::~Semaphore()
+{
+ sem_destroy(&semaphore);
+}
+
+void Semaphore::post()
+{
+ sem_post(&semaphore);
+}
+
+void Semaphore::wait()
+{
+ sem_wait(&semaphore);
+}
diff --git a/lib/semaphore.h b/lib/semaphore.h
new file mode 100644
index 0000000..85f4c09
--- /dev/null
+++ b/lib/semaphore.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * semaphore.h
+ *
+ * Sat Oct 8 17:44:13 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"
+#ifndef __MIAV_SEMAPHORE_H__
+#define __MIAV_SEMAPHORE_H__
+
+#include </usr/include/semaphore.h>
+
+class Semaphore {
+public:
+ Semaphore();
+ ~Semaphore();
+
+ void post();
+ void wait();
+
+private:
+ sem_t semaphore;
+};
+
+#endif/*__MIAV_SEMAPHORE_H__*/
diff --git a/lib/socket.cc b/lib/socket.cc
new file mode 100644
index 0000000..2ae88dc
--- /dev/null
+++ b/lib/socket.cc
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * socket.cc
+ *
+ * Mon Nov 8 10:49:33 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>
+
+#include "socket.h"
+
+#include <errno.h>
+
+Socket::Socket(Info *ginfo)
+{
+ info = ginfo;
+ connected = false;
+ err = 0;
+}
+
+Socket::Socket(u_short port, Info *ginfo)
+{
+ info = ginfo;
+ connected = false;
+ err = 0;
+
+ // create socket
+ ssocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ // PF_INET: ipv4, PF_INET6: ipv6
+ // tcp: IPPROTO_TCP
+ // upd: IPPROTO_UDP
+
+ if (ssocket < 0) {
+ err = 1;
+ info->error("Socket: socket() failed!");
+ }
+
+ socketaddr.sin_family = AF_INET; // Use "internet protocol" IP
+ socketaddr.sin_port = htons(port); // connect to that port
+ socketaddr.sin_addr.s_addr = INADDR_ANY;
+ // INADDR_ANY puts your IP address automatically
+}
+
+
+Socket::~Socket()
+{
+ // if(err) perror("Socket: No socket to kill");
+ // printf("Socket: I'm melting...[%d]\n", ssocket);
+ if(ssocket >= 0) close(ssocket); // close server socket
+}
+
+
+Socket Socket::slisten()
+{
+ Socket s = Socket(info);
+
+ if(err) {
+ //info->error("Socket: No socket present!");
+ return s;
+ }
+ if(!connected) {
+ // bind socket to address specified by "sa" parameter
+ err = bind(ssocket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+
+ if (err) {
+ info->error("Socket: bind() failed! %s", strerror(errno));
+ return s;
+ }
+
+ // start listen for connection - kernel will accept connection
+ // requests (max 5 in queue)
+ err = listen(ssocket, 5);
+ if(err) {
+ info->error("Socket: listen() failed! %s", strerror(errno));
+ return s;
+ }
+ }
+
+ // accept new connection and get its connection descriptor
+ int csalen = sizeof(s.socketaddr);
+
+ s.ssocket = accept(ssocket,
+ (struct sockaddr*)&s.socketaddr,
+ (socklen_t*)&csalen);
+
+ if (s.ssocket < 0) {
+ s.connected = false;
+ err = 1;
+ info->error("Socket: accept() failed! %s", strerror(errno));
+ return s;
+ }
+
+ connected = true;
+ s.connected = true;
+ return s;
+}
+
+
+int Socket::sconnect(char *ip)
+{
+ if(err) {
+ connected = false;
+ info->error("Socket: No socket present!");
+ return err;
+ }
+
+ // FIXME: gethostbyname()
+ socketaddr.sin_addr.s_addr = inet_addr(ip);
+ //inet_aton (ip, &socketaddr.sin_addr);
+
+ err = connect(ssocket, (struct sockaddr*)&socketaddr, sizeof(socketaddr));
+ if (err) {
+ connected = false;
+ info->error("Socket: connect() failed! %s", strerror(errno));
+ return err;
+ }
+ // fprintf(stderr, "Socket connected\n");
+ connected = true;
+ return 0;
+}
+
+
+bool Socket::isConnected()
+{
+ return connected;
+}
+
+bool Socket::hasError()
+{
+ return err != 0;
+}
diff --git a/lib/socket.h b/lib/socket.h
new file mode 100644
index 0000000..df2a133
--- /dev/null
+++ b/lib/socket.h
@@ -0,0 +1,61 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * socket.h
+ *
+ * Mon Nov 8 10:49:33 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 __MIAVLIB_SOCKET_H__
+#define __MIAVLIB_SOCKET_H__
+
+#include <stdio.h>
+#include <string.h>
+
+#include <unistd.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include "info.h"
+
+class Socket {
+public:
+ Socket(Info *ginfo);
+ Socket(u_short port, Info *ginfo);
+ ~Socket();
+ Socket slisten();
+ int sconnect(char *ip);
+ bool isConnected();
+ bool hasError();
+
+ struct sockaddr_in socketaddr;
+ int ssocket;
+ bool connected;
+
+private:
+ Info *info;
+ int err;
+};
+
+#endif/*__SOCKET_H__*/
diff --git a/lib/thread.cc b/lib/thread.cc
new file mode 100644
index 0000000..147cf00
--- /dev/null
+++ b/lib/thread.cc
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * thread.cc
+ *
+ * Sun Oct 31 12:12:20 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>
+
+#include "thread.h"
+#include <stdio.h>
+
+static void* thread_run(void *data) {
+ Thread *t = (Thread*)data;
+ t->thread_main();
+ return NULL;
+}
+
+Thread::Thread()
+{
+}
+
+Thread::~Thread()
+{
+}
+
+void Thread::run()
+{
+ pthread_attr_init(&attr);
+
+ pthread_create(&tid, &attr, thread_run, this);
+}
+
+void Thread::wait_stop()
+{
+ pthread_join(tid, NULL);
+}
diff --git a/lib/thread.h b/lib/thread.h
new file mode 100644
index 0000000..3d58d74
--- /dev/null
+++ b/lib/thread.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * thread.h
+ *
+ * Sun Oct 31 12:12:20 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 __THREAD_H__
+#define __THREAD_H__
+
+#include <pthread.h>
+#include <semaphore.h>
+
+class Thread {
+public:
+ Thread();
+ virtual ~Thread();
+
+ void run();
+ void wait_stop();
+
+ virtual void thread_main() = 0;
+
+private:
+ pthread_attr_t attr;
+ pthread_t tid;
+};
+
+#endif/*__THREAD_H__*/
diff --git a/lib/threadsafe_queue.cc b/lib/threadsafe_queue.cc
new file mode 100644
index 0000000..89f2d6a
--- /dev/null
+++ b/lib/threadsafe_queue.cc
@@ -0,0 +1,44 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue.cc
+ *
+ * Tue Sep 27 14:43:45 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"
+#include "threadsafe_queue.h"
+/*
+template <typename T>
+ThreadSafeQueue<T>::ThreadSafeQueue()
+{
+ pthread_mutex_init (&mutex, NULL);
+ sem_init(&semaphore, 0, 0);
+}
+
+template <typename T>
+ThreadSafeQueue<T>::~ThreadSafeQueue()
+{
+ pthread_mutex_destroy(&mutex);
+ sem_destroy(&semaphore);
+}
+
+*/
diff --git a/lib/threadsafe_queue.h b/lib/threadsafe_queue.h
new file mode 100644
index 0000000..b6d5725
--- /dev/null
+++ b/lib/threadsafe_queue.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue.h
+ *
+ * Tue Sep 27 14:01:01 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"
+#ifndef __MIAV_THREADSAFE_QUEUE_H__
+#define __MIAV_THREADSAFE_QUEUE_H__
+
+#include "mutex.h"
+#include "semaphore.h"
+
+template <typename T>
+class ThreadSafeQueue {
+public:
+ ThreadSafeQueue() {
+ // pthread_mutex_init (&mutex, NULL);
+ // sem_init(&semaphore, 0, 0);
+ }
+
+ virtual ~ThreadSafeQueue() {
+ // pthread_mutex_destroy(&mutex);
+ //sem_destroy(&semaphore);
+ }
+
+ virtual void push(T t) = 0;
+ virtual T pop() = 0;
+ virtual int size() = 0;
+
+protected:
+ // pthread_mutex_t mutex;
+ Mutex mutex;
+ //sem_t semaphore;
+ Semaphore semaphore;
+};
+
+#endif/*__MIAV_THREADSAFE_QUEUE_H__*/
diff --git a/lib/threadsafe_queue_fifo.cc b/lib/threadsafe_queue_fifo.cc
new file mode 100644
index 0000000..6dbcb67
--- /dev/null
+++ b/lib/threadsafe_queue_fifo.cc
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue_fifo.cc
+ *
+ * Tue Sep 27 14:01:10 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"
+#include "threadsafe_queue_fifo.h"
+
+ThreadSafeQueueFIFO::ThreadSafeQueueFIFO()
+{
+}
+
+ThreadSafeQueueFIFO::~ThreadSafeQueueFIFO()
+{
+}
+
+void ThreadSafeQueueFIFO::push(FrameVector *framevector)
+{
+ mutex.lock();
+ queue.push(framevector);
+ mutex.unlock();
+
+ semaphore.post();
+}
+
+FrameVector *ThreadSafeQueueFIFO::pop()
+{
+ semaphore.wait();
+
+ FrameVector *framevector;
+
+ mutex.lock();
+ framevector = queue.front();
+ queue.pop();
+ mutex.unlock();
+
+ return framevector;
+}
+
+int ThreadSafeQueueFIFO::size()
+{
+ int sz;
+
+ mutex.lock();
+ sz = queue.size();
+ mutex.unlock();
+
+ return sz;
+}
diff --git a/lib/threadsafe_queue_fifo.h b/lib/threadsafe_queue_fifo.h
new file mode 100644
index 0000000..ee3ac3b
--- /dev/null
+++ b/lib/threadsafe_queue_fifo.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue_fifo.h
+ *
+ * Tue Sep 27 14:01:10 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"
+#ifndef __MIAV_THREADSAFE_QUEUE_FIFO_H__
+#define __MIAV_THREADSAFE_QUEUE_FIFO_H__
+
+#include "threadsafe_queue.h"
+
+#include "frame.h"
+
+#include <queue>
+
+class ThreadSafeQueueFIFO: public ThreadSafeQueue<FrameVector*> {
+public:
+ ThreadSafeQueueFIFO();
+ ~ThreadSafeQueueFIFO();
+
+ void push(FrameVector* framevector);
+ FrameVector* pop();
+ int size();
+
+private:
+ std::queue<FrameVector*> queue;
+};
+
+#endif/*__MIAV_THREADSAFE_QUEUE_FIFO_H__*/
diff --git a/lib/threadsafe_queue_priority.cc b/lib/threadsafe_queue_priority.cc
new file mode 100644
index 0000000..df7ae8c
--- /dev/null
+++ b/lib/threadsafe_queue_priority.cc
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue_priority.cc
+ *
+ * Tue Sep 27 14:01:24 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"
+#include "threadsafe_queue_priority.h"
+
+#include "util.h"
+
+ThreadSafeQueuePriority::ThreadSafeQueuePriority(Info* i, unsigned int number)
+ // : ThreadSafeQueue< Frame* >()
+{
+ info = i;
+ framenumber = number;
+}
+
+ThreadSafeQueuePriority::~ThreadSafeQueuePriority()
+{
+}
+
+void ThreadSafeQueuePriority::push(Frame *frame)
+{
+ // Lock mutex
+ // pthread_mutex_lock( &mutex );
+ mutex.lock();
+ queue.push(frame);
+ // pthread_mutex_unlock( &mutex );
+ mutex.unlock();
+ // Unlock mutex
+
+ // sem_post(&semaphore);
+ semaphore.post();
+}
+
+Frame *ThreadSafeQueuePriority::pop()
+{
+ semaphore.wait();
+ // sem_wait(&semaphore);
+
+ Frame *tmpframe = NULL;
+ Frame *frame = NULL;
+
+ while( frame == NULL ) {
+ // Lock mutex
+ // pthread_mutex_lock( &mutex );
+ mutex.lock();
+
+ tmpframe = queue.top();
+
+ if(tmpframe && tmpframe->number == framenumber ) {
+ queue.pop();
+ frame = tmpframe;
+ framenumber++;
+ }
+
+ // pthread_mutex_unlock( &mutex );
+ mutex.unlock();
+ // Unlock mutex
+
+ if(frame == NULL) sleep_0_2_frame();
+ }
+
+ return frame;
+}
+
+int ThreadSafeQueuePriority::size()
+{
+ int sz;
+
+ // Lock mutex
+ // pthread_mutex_lock( &mutex );
+ mutex.lock();
+ sz = queue.size();
+ // pthread_mutex_unlock( &mutex );
+ mutex.unlock();
+ // Unlock mutex
+
+ return sz;
+}
diff --git a/lib/threadsafe_queue_priority.h b/lib/threadsafe_queue_priority.h
new file mode 100644
index 0000000..8d3cdf1
--- /dev/null
+++ b/lib/threadsafe_queue_priority.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * threadsafe_queue_priority.h
+ *
+ * Tue Sep 27 14:01:24 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"
+#ifndef __MIAV_THREADSAFE_QUEUE_PRIORITY_H__
+#define __MIAV_THREADSAFE_QUEUE_PRIORITY_H__
+
+#include "threadsafe_queue.h"
+
+#include "frame.h"
+
+#include <queue>
+#include <functional>
+
+#include "info.h"
+
+// Method for use, when comparing Frames in priority queue.
+template <typename T>
+struct priority : std::binary_function<T, T, bool> {
+ bool operator() (const T& a, const T& b) const {
+ return ((Frame*)a)->number > ((Frame*)b)->number;
+ }
+};
+
+class ThreadSafeQueuePriority: public ThreadSafeQueue< Frame* > {
+public:
+ ThreadSafeQueuePriority(Info *info, unsigned int framenumber = 0);
+ ~ThreadSafeQueuePriority();
+
+ void push(Frame *frame);
+ Frame *pop();
+ int size();
+
+private:
+ Info* info;
+
+ unsigned int framenumber;
+ std::priority_queue< Frame*, std::vector<Frame*>, priority<Frame*> > queue;
+};
+
+#endif/*__MIAV_THREADSAFE_QUEUE_PRIORITY_H__*/
diff --git a/lib/util.cc b/lib/util.cc
new file mode 100644
index 0000000..11f1402
--- /dev/null
+++ b/lib/util.cc
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * util.cc
+ *
+ * Sun Oct 31 12:12:20 CET 2004
+ * Copyright 2004 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>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// For nanosleep
+#include <time.h>
+
+#include "util.h"
+
+void *xmalloc(size_t s)
+{
+ void *p;
+ assert(s > 0);
+
+ p = malloc(s);
+ if(!p) {
+ fprintf(stderr, "Out of memory in xmalloc\n");
+ exit(1);
+ }
+ memset(p, 0, s);
+ return p;
+}
+
+void *xrealloc(void *b, size_t s)
+{
+ void *p;
+ assert(s > 0);
+
+ if(!b) return xmalloc(s);
+
+ p = realloc(b, s);
+ if(!p) {
+ fprintf(stderr, "Out of memory in xrealloc\n");
+ exit(1);
+ }
+ return p;
+}
+
+void sleep_1_frame()
+{
+ // Sleep 1/25th of a second
+
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 1000000000L / 25L; // 1000ms / 25
+ nanosleep(&ts, NULL);
+}
+
+void sleep_0_2_frame()
+{
+ // Sleep 1/25th of a second
+
+ struct timespec ts;
+
+ ts.tv_sec = 0;
+ ts.tv_nsec = 8000000L;//1000000000L / 25L * 0.2; // 1000ms / 25
+ nanosleep(&ts, NULL);
+}
diff --git a/lib/util.h b/lib/util.h
new file mode 100644
index 0000000..ef21e06
--- /dev/null
+++ b/lib/util.h
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * util.h
+ *
+ * Mon Nov 8 10:49:33 CET 2004
+ * Copyright 2004 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"
+#ifndef __RTVIDEOREC_UTIL_H
+#define __RTVIDEOREC_UTIL_H
+
+#include <stdio.h>
+//#include <stdlib.h>
+
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+
+void *xmalloc(size_t s);
+void *xrealloc(void *b, size_t s);
+
+void sleep_1_frame();
+void sleep_0_2_frame();
+//#ifdef __cplusplus
+//}
+//#endif
+
+#endif
diff --git a/server/audio_encoder.cc b/server/audio_encoder.cc
new file mode 100644
index 0000000..6e412c3
--- /dev/null
+++ b/server/audio_encoder.cc
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audio_encoder.cc
+ *
+ * Sat Sep 17 18:38:45 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"
+#include "audio_encoder.h"
+#include "util.h"
+
+#include "liblame_wrapper.h"
+
+AudioEncoder::AudioEncoder(ThreadSafeQueuePriority *audio_input_queue,
+ ThreadSafeQueuePriority *audio_output_queue,
+ Info *i)
+{
+ info = i;
+ info->info("AudioEncoder");
+
+ running = true;
+
+ input_queue = audio_input_queue;
+ output_queue = audio_output_queue;
+}
+
+AudioEncoder::~AudioEncoder()
+{
+}
+
+void AudioEncoder::thread_main()
+{
+ info->info("AudioEncoder::run");
+
+ // Run with slightly lower priority than MovEncoderWriter
+ nice(1);
+
+ Frame *in_frame = NULL;
+ Frame *out_frame = NULL;
+
+ LibLAMEWrapper lame(info);
+
+ while(running) {
+ in_frame = input_queue->pop();
+
+ if(in_frame == NULL) info->error("AudioEncoder: in_frame == NULL!");
+
+ // Check for end of stream
+ if(in_frame->endOfFrameStream == true) {
+ info->info("endOfFrameStream in AudioEncoder");
+ running = false;
+ out_frame = lame.close();
+ } else {
+ // Encode audio
+ out_frame = lame.encode(in_frame);
+ }
+ out_frame->number = in_frame->number;
+ out_frame->endOfFrameStream = in_frame->endOfFrameStream;
+
+ delete in_frame;
+ in_frame = NULL;
+
+ output_queue->push(out_frame);
+ }
+
+ info->info("AudioEncoder::stop");
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+
+void AudioEncoder::thread_main()
+{
+ info->info("AudioEncoder::run");
+
+#ifndef NEW_QUEUE
+ unsigned int queuesize = 0;
+ Frame *tmpframe;
+#endif
+
+ // Run with slightly lower priority than MovEncoderWriter
+ nice(2);
+
+ Frame *in_frame = NULL;
+ Frame *out_frame = NULL;
+
+ LibLAMEWrapper lame(info);
+
+ while(running) {
+ info->info("fisk");
+#ifdef NEW_QUEUE
+ in_frame = input_queue->pop();
+#else
+ sem_wait(input_sem);
+
+ // If no frame is in the buffer, get one from the queue
+ while( in_frame == NULL ) {
+
+ // sem_wait(input_sem);
+
+ // Lock output mutex
+ pthread_mutex_lock( input_mutex );
+ tmpframe = inputqueue->top();
+
+ if(tmpframe && tmpframe->number == frame_number) {
+ inputqueue->pop();
+ queuesize = inputqueue->size();
+ in_frame = tmpframe;
+ frame_number++;
+ }
+
+ pthread_mutex_unlock( input_mutex );
+ // Unlock output mutex
+
+ sleep_0_2_frame();
+ }
+#endif
+
+ // Check for end of stream
+ if(in_frame->endOfFrameStream == true) {
+ info->info("endOfFrameStream in AudioEncoder");
+ running = false;
+ out_frame = lame.close();
+ } else {
+ // Encode audio
+ out_frame = lame.encode(in_frame);
+ }
+ out_frame->number = in_frame->number;
+ out_frame->endOfFrameStream = in_frame->endOfFrameStream;
+
+ delete in_frame;
+ in_frame = NULL;
+
+#ifdef NEW_QUEUE
+ output_queue->push(out_frame);
+#else
+ // Lock output mutex
+ pthread_mutex_lock(output_mutex);
+ outputqueue->push(out_frame);
+ pthread_mutex_unlock(output_mutex);
+ // Unlock output mutex
+
+ // Kick multiplexer (audio)
+ sem_post(output_sem);
+#endif
+ }
+
+#ifndef NEW_QUEUE
+ // Kick multiplexer (audio)
+ sem_post(output_sem);
+#endif
+
+ info->info("AudioEncoder::stop");
+}
+*/
diff --git a/server/audio_encoder.h b/server/audio_encoder.h
new file mode 100644
index 0000000..9d86178
--- /dev/null
+++ b/server/audio_encoder.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * audio_encoder.h
+ *
+ * Sat Sep 17 18:38:45 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"
+#ifndef __MIAV_AUDIO_ENCODER_H__
+#define __MIAV_AUDIO_ENCODER_H__
+
+#include "frame.h"
+#include "util.h"
+
+#include "thread.h"
+#include <pthread.h>
+
+#include "info.h"
+
+#include "threadsafe_queue_priority.h"
+
+class AudioEncoder : public Thread {
+public:
+ AudioEncoder(ThreadSafeQueuePriority *audio_input_queue,
+ ThreadSafeQueuePriority *audio_output_queue,
+ Info *info);
+ ~AudioEncoder();
+
+ void thread_main();
+
+ volatile bool running;
+
+private:
+ Info *info;
+
+ ThreadSafeQueuePriority *input_queue;
+ ThreadSafeQueuePriority *output_queue;
+};
+
+
+#endif/*__MIAV_AUDIO_ENCODER_H__*/
diff --git a/server/config.h b/server/config.h
new file mode 100644
index 0000000..e7101c9
--- /dev/null
+++ b/server/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/server/dvfile.cc b/server/dvfile.cc
new file mode 100644
index 0000000..7d83255
--- /dev/null
+++ b/server/dvfile.cc
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * dvfile.cc
+ *
+ * Thu Jul 28 17:30:48 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 "dvfile.h"
+
+#include "dv.h"
+#include "util.h"
+
+dvfile::dvfile(Info* i)
+{
+ info = i;
+ fp = fopen(TEST_MOVIE, "r");
+ if(!fp) info->error("Couldn't open %s for reading.", TEST_MOVIE);
+}
+
+dvfile::~dvfile()
+{
+ fclose(fp);
+}
+
+unsigned char *dvfile::readFrame()
+{
+ unsigned char *frame = new unsigned char[DVPACKAGE_SIZE];
+
+ sleep_1_frame();
+
+ if(fp) {
+ while(fread(frame, DVPACKAGE_SIZE, 1, fp) == 0) {
+ fseek(fp, 0L, SEEK_SET);
+ }
+ } else {
+ memset(frame, 0, sizeof(frame));
+ }
+
+ return frame;
+}
diff --git a/server/dvfile.h b/server/dvfile.h
new file mode 100644
index 0000000..dc91a14
--- /dev/null
+++ b/server/dvfile.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * dvfile.h
+ *
+ * Thu Jul 28 17:30:48 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_DVFILE_H__
+#define __MIAV_DVFILE_H__
+
+#include "frame_stream.h"
+
+#include <stdio.h>
+
+#include "info.h"
+
+#define TEST_MOVIE PIXMAPS"/dummy.dv"
+
+class dvfile : public frame_stream {
+public:
+ dvfile(Info* info);
+ ~dvfile();
+
+ unsigned char *readFrame();
+
+private:
+ Info* info;
+ FILE* fp;
+};
+
+#endif/*__MIAV_DVFILE_H__*/
diff --git a/server/img_encoder.cc b/server/img_encoder.cc
new file mode 100644
index 0000000..9282dc0
--- /dev/null
+++ b/server/img_encoder.cc
@@ -0,0 +1,196 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * img_encoder.cc
+ *
+ * Mon Nov 15 19:45:07 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 "img_encoder.h"
+#include <stdio.h>
+
+#include "debug.h"
+
+extern "C" {
+#include <jpeglib.h>
+}
+
+#include "jpeg_mem_dest.h"
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+ImgEncoder::ImgEncoder(const char* cpr, Info *i)
+{
+ info = i;
+
+ // Create path and filename
+ char fname[256];
+ string *server_root;
+ char birthmonth[3];
+ char date[32];
+ char encrypted_cpr[32];
+
+ // Get server root
+ server_root = config->readString("server_image_root");
+
+ // Copy the bytes representing the birth month from the cpr
+ // [dd][mm][yy]-[nn][nn]
+ strncpy(birthmonth, &cpr[2], 2);
+ birthmonth[2] = 0;
+
+ // Create date (today) in [yyyy][mm][dd]
+ struct tm *ltime;
+ time_t t = time(NULL);
+ ltime = localtime(&t);
+ sprintf(date, "%.4d%.2d%.2d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon,
+ ltime->tm_mday);
+
+ // Create 'encrypted' cpr, reverse numbers, skip month, and subtract from 9
+ // [d1][d2][m1][m2][y1][y2]-[n1][n2][n3][n4]
+ // =>
+ // [9-n4][9-n3][9-n2][9-n1][9-y2][9-y1][9-d2][9-d1]
+ memset(encrypted_cpr, 0, sizeof(encrypted_cpr));
+ int p = strlen(cpr) - 1;
+ int cnt = 0;
+ while(p) {
+ encrypted_cpr[cnt] = cpr[p];
+ p--;
+ if(p == 2) p--;
+ if(cpr[p] == '-' || p == 3) p--;
+ cnt++;
+ }
+
+ sprintf(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, encrypted_cpr, cpr, date);
+
+ file = new File(fname, "jpg", info);
+}
+
+
+ImgEncoder::~ImgEncoder()
+{
+ delete file;
+}
+
+
+void ImgEncoder::encode(Frame *dvframe, int quality)
+{
+ unsigned char rgb[720*576*4];
+
+ getRGB(dvframe, rgb);
+ writeJPEGFile(quality, rgb, 720, 576);
+}
+
+
+void ImgEncoder::writeJPEGFile(int quality, unsigned char *rgb, int image_width, int image_height)
+{
+ JSAMPLE *image_buffer = (JSAMPLE*)rgb;
+
+ size_t buffersize = (image_width * image_height * 3) + JPEG_HEADER_PAD;
+ char *jpeg_output_buffer = new char [buffersize];
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+
+ JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
+ int row_stride; // physical row width in image buffer
+
+ // Allocate and initialize JPEG compression object
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ // Specify data destination (see jpeg_mem_dest)
+ jpeg_mem_dest(&cinfo, jpeg_output_buffer, &buffersize);
+
+ // Set compression parameters
+ cinfo.image_width = image_width; // image width and height, in pixels
+ cinfo.image_height = image_height;
+ cinfo.input_components = 3; // # of color components per pixel
+ cinfo.in_color_space = JCS_RGB; // colorspace of input image
+
+ jpeg_set_defaults(&cinfo);
+
+ jpeg_set_quality(&cinfo, quality, TRUE); // limit to baseline-JPEG values
+
+ // Start compressor
+ jpeg_start_compress(&cinfo, TRUE);
+
+ // While (scan lines remain to be written)
+ row_stride = image_width * 3; // JSAMPLEs per row in image_buffer
+
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
+ (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ // Finish compression
+ jpeg_finish_compress(&cinfo);
+
+ // Release JPEG compression object
+ jpeg_destroy_compress(&cinfo);
+
+ info->info("JPEG buffersize: %d", buffersize);
+ file->Write(jpeg_output_buffer, buffersize);
+ delete jpeg_output_buffer;
+}
+
+void ImgEncoder::getRGB(Frame *frame, unsigned char *rgb)
+{
+ unsigned char *pixels[3];
+ int pitches[3];
+
+ pixels[ 0 ] = rgb;
+ pixels[ 1 ] = NULL;
+ pixels[ 2 ] = NULL;
+
+ pitches[ 0 ] = 720 * 3;
+ 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_rgb,
+ pixels,
+ pitches);
+
+ dv_decoder_free(decoder);
+}
diff --git a/server/img_encoder.h b/server/img_encoder.h
new file mode 100644
index 0000000..9745a8f
--- /dev/null
+++ b/server/img_encoder.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * img_encoder.h
+ *
+ * Mon Nov 15 19:45:07 CET 2004
+ * Copyright 2004 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"
+#ifndef __RTVIDEOREC_IMGENCODER_H
+#define __RTVIDEOREC_IMGENCODER_H
+
+#include <stdio.h>
+
+#include "frame.h"
+#include "util.h"
+
+//#include <stdlib.h>
+//#include <string.h>
+
+#include "info.h"
+#include "file.h"
+
+#define VIDEO_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
+#define JPEG_HEADER_PAD 500
+
+class ImgEncoder {
+public:
+ ImgEncoder(const char* cpr, Info *info);
+ ~ImgEncoder();
+ void encode(Frame *frame, int quality);
+ void writeJPEGFile(int quality,
+ unsigned char *image_buffer, // Points to large array of R,G,B-order data
+ int image_width, // Number of columns in image
+ int image_height); // Number of rows in image
+
+private:
+ File *file;
+ Info *info;
+ void getRGB(Frame *frame, unsigned char *rgb);
+};
+
+#endif /*__RTVIDEOREC_IMGENCODER_H*/
+
diff --git a/server/info_console.cc b/server/info_console.cc
new file mode 100644
index 0000000..ce406fb
--- /dev/null
+++ b/server/info_console.cc
@@ -0,0 +1,101 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_console.cc
+ *
+ * Tue May 3 09:35:03 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 "info_console.h"
+
+#include "miav_config.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+
+InfoConsole::InfoConsole(MiavConfig *c): Info()
+{
+ this->config = c;
+ log_filename = *(this->config->readString("server_log_file"));
+}
+
+InfoConsole::~InfoConsole()
+{
+ pthread_mutex_destroy(&mutex);
+}
+
+void InfoConsole::error(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Error: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Error: %s", buf);
+}
+
+void InfoConsole::warn(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Warning: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Warning: %s", buf);
+}
+
+void InfoConsole::info(char *fmt, ...)
+{
+ char buf[1024];
+
+ pthread_mutex_lock(&mutex);
+ // Beginning of safezone
+
+ va_list argp;
+ va_start(argp, fmt);
+ // fprintf(stderr, "Info: ["); vfprintf(stderr, fmt, argp); fprintf(stderr, "]\n"); fflush(stderr);
+ vsprintf(buf, fmt, argp);
+ va_end(argp);
+
+ // End of safezone
+ pthread_mutex_unlock(&mutex);
+
+ log("Info: %s", buf);
+}
diff --git a/server/info_console.h b/server/info_console.h
new file mode 100644
index 0000000..2adcad6
--- /dev/null
+++ b/server/info_console.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * info_console.h
+ *
+ * Tue May 3 09:35:03 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_CONSOLE_H__
+#define __MIAV_INFO_CONSOLE_H__
+
+#include "info.h"
+
+#include "miav_config.h"
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <string>
+using namespace std;
+
+class InfoConsole: public Info {
+public:
+ InfoConsole(MiavConfig *config);
+ ~InfoConsole();
+
+ void error(char* fmt, ...);
+ void warn(char* fmt, ...);
+ void info(char* fmt, ...);
+
+private:
+};
+
+#endif/*__MIAV_INFO_CONSOLE_H__*/
diff --git a/server/iso11172-1.h b/server/iso11172-1.h
new file mode 100644
index 0000000..ee8f408
--- /dev/null
+++ b/server/iso11172-1.h
@@ -0,0 +1,161 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-1.h
+ *
+ * Wed Aug 31 13:48:30 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.
+ */
+
+/*
+ * This file contains symbols used to create an ISO11172-1 compatible multiplexed
+ * MPEG stream.
+ */
+
+#include "config.h"
+#ifndef __MIAV_ISO11172_1_H__
+#define __MIAV_ISO11172_1_H__
+
+#define CLOCK_90KHZ 90000
+
+namespace ISO11172_1 {
+ ////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////
+ // 64 bits (8 bytes)
+ typedef struct {
+ unsigned long long int marker_bit3:1;
+ unsigned long long int system_clock_reference3:15;
+ unsigned long long int marker_bit2:1;
+ unsigned long long int system_clock_reference2:15;
+ unsigned long long int marker_bit1:1;
+ unsigned long long int system_clock_reference1:3;
+ unsigned long long int padding:4;
+ unsigned long long int stuffing_byte:8;
+ unsigned long long int packet_length:16;
+ } packet_header;
+
+ typedef struct {
+ unsigned long long int marker_bit5:1;
+ unsigned long long int mux_rate:22;
+ unsigned long long int marker_bit4:1;
+ unsigned long long int marker_bit3:1;
+ unsigned long long int system_clock_reference3:15;
+ unsigned long long int marker_bit2:1;
+ unsigned long long int system_clock_reference2:15;
+ unsigned long long int marker_bit1:1;
+ unsigned long long int system_clock_reference1:3;
+ unsigned long long int padding:4;
+ } pack_header;
+
+ typedef struct {
+ unsigned long long int reserved_byte:8;
+ unsigned long long int video_bound:5;
+ unsigned long long int marker_bit3:1;
+ unsigned long long int system_video_clock_flag:1;
+ unsigned long long int system_audio_clock_flag:1;
+ unsigned long long int CSPS_flag:1;
+ unsigned long long int fixed_flag:1;
+ unsigned long long int audio_bound:6;
+ unsigned long long int marker_bit2:1;
+ unsigned long long int rate_bound:22;
+ unsigned long long int marker_bit1:1;
+ unsigned long long int header_length:16;
+ } system_header;
+
+ typedef struct {
+ unsigned long int STD_buffer_size_bound:13;
+ unsigned long int STD_buffer_bound_scale:1;
+ unsigned long int market_bits:2;
+ unsigned long int stream_id:8;
+ } stream_description;
+
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+ const char pack_start_code[] = "\x00\x00\x01\xBA";
+ const char system_header_start_code[] = "\x00\x00\x01\xBB";
+ const char packet_start_code_prefix[] = "\x00\x00\x01";
+ const char stream_id_video1[] = "\xE3";
+ const char stream_id_video2[] = "\xE4";
+ const char stream_id_video3[] = "\xE5";
+ const char stream_id_video4[] = "\xE6";
+ const char stream_id_video5[] = "\xE7";
+ const char stream_id_video6[] = "\xE8";
+ const char stream_id_video7[] = "\xE9";
+ const char stream_id_video8[] = "\xEA";
+ const char stream_id_audio1[] = "\xC0";
+ const char stream_id_audio2[] = "\xC1";
+ const char stream_id_audio3[] = "\xC2";
+ const char stream_id_audio4[] = "\xC3";
+ const char stream_id_audio5[] = "\xC4";
+ const char stream_id_audio6[] = "\xC5";
+ const char stream_id_audio7[] = "\xC6";
+ const char stream_id_audio8[] = "\xC7";
+ const char stream_id_padding[] = "\xBE";
+ const char end_code[] = "\x00\x00\x01\xB9";
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+ /**
+ * SCR stands for System Clock Reference
+ */
+ inline unsigned int SCR(unsigned int previous_SCR,
+ unsigned int pack_header_size,
+ unsigned int packets_per_pack,
+ unsigned int packet_data_size,
+ unsigned int Rmux)
+ {
+ // To prevent a crash when doing division.
+ if(Rmux == 0) Rmux = 1;
+ return previous_SCR + (unsigned int)((double)(pack_header_size +
+ (packets_per_pack * packet_data_size)) *
+ (double)CLOCK_90KHZ / (double)Rmux);
+ }
+
+ /**
+ * Calculates Rmux according to subclause A.5.4
+ * mux stands for multiplexing and R for Rate,
+ * so Rmux is the rate of the multiplexing.
+ */
+ inline unsigned int Rmux(unsigned int video_data_rate,
+ unsigned int audio_data_rate,
+ unsigned int packet_header_size,
+ unsigned int pack_header_size,
+ unsigned int packets_per_pack,
+ unsigned int packet_data_size)
+ {
+ // To prevent a crash when doing division.
+ if(packets_per_pack == 0) packets_per_pack = 1;
+ if(packet_data_size == 0) packet_data_size = 1;
+
+ return (unsigned int)(
+ ((double)video_data_rate + (double)audio_data_rate) *
+ (1.0 + ((double)packet_header_size + (double)pack_header_size / (double)packets_per_pack)
+ / (double)packet_data_size)
+ );
+ }
+
+
+};
+
+#endif/*__MIAV_ISO11172_1_H__*/
diff --git a/server/iso11172-2.h b/server/iso11172-2.h
new file mode 100644
index 0000000..f2e2fa3
--- /dev/null
+++ b/server/iso11172-2.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-2.h
+ *
+ * Tue Sep 6 13:31:04 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"
+#ifndef __MIAV_ISO11172_2_H__
+#define __MIAV_ISO11172_2_H__
+
+namespace ISO11172_2 {
+ ////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////
+ typedef struct {
+ unsigned long int picture_rate:4;
+ unsigned long int pel_aspect_ratio:4;
+ unsigned long int vertical_size:12;
+ unsigned long int horizontal_size:12;
+ } sequence_header_1;
+
+ typedef struct {
+ unsigned long int load_non_intra_quantizer_flag:1;
+ unsigned long int load_intra_quantizer_flag:1;
+ unsigned long int constrained_parameter_flag:1;
+ unsigned long int vbv_buffer_size:10;
+ unsigned long int marker_bit:1;
+ unsigned long int bitrate:18;
+ } sequence_header_2;
+
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+ const char picture_start_code[] = "\x00\x00\x01\x00";
+ const char slice_start_code_prefix[] ="\x00\x00\x01";
+ // const char _code = "\x00\x00\x01\xB0"; //Reserved
+ // const char _code = "\x00\x00\x01\xB1"; //Reserved
+ const char user_data_start_code[] = "\x00\x00\x01\xB2";
+ const char sequence_header_code[] = "\x00\x00\x01\xB3";
+ const char sequence_error_code[] = "\x00\x00\x01\xB4";
+ const char sequence_start_code[] = "\x00\x00\x01\xB5";
+ // const char _code = "\x00\x00\x01\xB6"; //Reserved
+ const char sequence_end_code[] = "\x00\x00\x01\xB7";
+ const char group_start_code[] = "\x00\x00\x01\xB8";
+ const char system_start_code_prefix[] = "\x00\x00\x01";
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+
+};
+
+#endif/*__MIAV_ISO11172_2_H__*/
diff --git a/server/iso11172-3.h b/server/iso11172-3.h
new file mode 100644
index 0000000..d3eda79
--- /dev/null
+++ b/server/iso11172-3.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * iso11172-3.h
+ *
+ * Tue Sep 6 13:10:48 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"
+#ifndef __MIAV_ISO11172_3_H__
+#define __MIAV_ISO11172_3_H__
+
+namespace ISO11172_3 {
+ ////////////////////////////////////////////////////
+ // Types
+ ////////////////////////////////////////////////////
+ typedef struct {
+ unsigned long int emphasis:2;
+ unsigned long int original_home:1;
+ unsigned long int copyright:1;
+ unsigned long int mode_extension:2;
+ unsigned long int mode:2;
+ unsigned long int private_bit:1;
+ unsigned long int padding_bit:1;
+ unsigned long int sampling_frequency:2;
+ unsigned long int bitrate_index:4;
+ unsigned long int protection_bit:1;
+ unsigned long int layer:2;
+ unsigned long int ID:1;
+ unsigned long int syncword:12;
+ } header;
+
+ ////////////////////////////////////////////////////
+ // Constants
+ ////////////////////////////////////////////////////
+
+ typedef enum {
+ ID_RESERVED = 0,
+ ID_MPEG = 1
+ } IDs;
+
+ typedef enum {
+ LAYER_RESERVED = 0x00,
+ LAYER_III = 0x01,
+ LAYER_II = 0x10,
+ LAYER_I = 0x11
+ } layers;
+
+ typedef enum {
+ CRC_ON = 0,
+ CRC_OFF = 1
+ } crcs;
+
+ typedef enum {
+ MODE_STEREO = 0x00,
+ MODE_JOINT_STEREO = 0x01,
+ MODE_DUAL_CHANNEL = 0x10,
+ MODE_SINGLE_CHANNEL = 0x11,
+ } modes;
+
+ ////////////////////////////////////////////////////
+ // Methods
+ ////////////////////////////////////////////////////
+
+};
+
+#endif/*__MIAV_ISO11172_3_H__*/
diff --git a/server/libfame_wrapper.cc b/server/libfame_wrapper.cc
new file mode 100644
index 0000000..a663df6
--- /dev/null
+++ b/server/libfame_wrapper.cc
@@ -0,0 +1,273 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libfame_wrapper.cc
+ *
+ * Sat Jul 2 11:11:31 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 "libfame_wrapper.h"
+
+#include <errno.h>
+
+#include "miav_config.h"
+#include "frame.h"
+
+LibFAMEWrapper::LibFAMEWrapper(Info *i)
+{
+ info = i;
+
+ // FIXME: Hmmm... should this be detected somewhere?!
+ int w = 720;
+ int h = 576;
+
+ // Initialize yuv structure.
+ yuv.w = w;
+ yuv.h = h;
+ yuv.p = w;
+ yuv.y = new unsigned char [w*h * 2];
+ yuv.u = new unsigned char [w*h];// [w*h/4]
+ yuv.v = new unsigned char [w*h];// [w*h/4]
+
+ calc_bitrate = 0;
+ frame_number = 0;
+
+ ////////////LIBDV STUFF///////////////
+
+ dvdecoder = NULL; // Initialize in encode method
+
+ /////////LIBFAME STUFF///////////
+
+ // Allocate the output buffer.
+// fame_buffer = new unsigned char [FAME_BUFFER_SIZE];
+
+ // Open a new session of the fame library.
+ // (If initialization was successful, it returns a non-null context which
+ // can then be used for subsequent library calls.)
+ fame_context = fame_open();
+ if(!fame_context) {
+ info->error("Unable to open FAME context, due to the following error: %s", strerror(errno));
+ return;
+ }
+
+ /*
+ typedef struct _fame_parameters_ {
+ int width; // width of the video sequence
+ int height; // height of the video sequence
+ char const *coding; // coding sequence
+ int quality; // video quality
+ int slices_per_frame; // number of slices per frame
+ unsigned int frames_per_sequence; // number of frames per sequence
+ int frame_rate_num; // numerator of frames per second
+ int frame_rate_den; // denominator of frames per second
+ unsigned int shape_quality; // binary shape quality
+ unsigned int search_range; // motion estimation search range
+ unsigned char verbose; // verbosity
+ } fame_parameters_t;
+ */
+ // width and height specify the size of each frames of the video sequence.
+ // Both must be multiple of 16. width and height must be less than 4096x4096
+ fame_par.width = 720;
+ fame_par.height = 576;
+
+ // coding is a string of I, P or B characters representing the sequence of
+ // frames the encoder must produce. I frames are intra-coded frames (similar
+ // to JPEG), whereas P and B frames are motion compressed, respectively
+ // predicted from past reference (I or P) frame, or bidirectionally predicted
+ // from past and future reference frame.
+ fame_par.coding = config->readString("frame_sequence")->c_str();
+
+ // quality is a percentage, which controls compression versus quality.
+ fame_par.quality = config->readInt("video_quality");
+
+ // Bitrate
+ fame_par.bitrate = config->readInt("video_bitrate") * 1000; // video bitrate in bytes pr second (0=VBR)
+
+ // slices_per_frame is the number of frame slices per frame. More slices provide
+ // better error recovery. There must be at least one slice per frame, and at most
+ // height / 16
+ fame_par.slices_per_frame = 1;//fame_par.height / 16;
+
+ // frames_per_sequence is the maximum number of frames contained in a video
+ // sequence.
+ fame_par.frames_per_sequence = 0xffffffff; // Unlimited length
+
+ // frame_rate_num/frame_rate_den specify the number of frames per second for
+ // playback.
+ fame_par.frame_rate_num = 25; // 25 / 1 fps = 25 fps
+ fame_par.frame_rate_den = 1;
+
+ // shape_quality is percentage determing the average binary shape accuracy in
+ // video with arbitrary shape.
+ fame_par.shape_quality = 100; // Original shape
+
+ // search_range specifies the motion estimation search range in pixel unit.
+ // Small search ranges work best with slow motion videos, whereas larger search
+ // ranges are rather for fast motion videos.
+ fame_par.search_range = 0; // Adaptive search range
+
+ // verbose when set to 1 outputs information on copyright, modules used and
+ // current frame on standard error.
+ fame_par.verbose = 0;
+
+ static const char profilename[] = "MIaV\0";
+ fame_par.profile = profilename; // profile name
+ fame_par.total_frames = 0; // total number of frames
+
+ if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg4") == 0) {
+
+ info->info("Using mpeg4 compression.");
+ fame_object_t *object;
+
+ object = fame_get_object(fame_context, "profile/mpeg4/simple");
+ if(object) fame_register(fame_context, "profile", object);
+
+ } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
+
+ info->info("Using mpeg1 compression.");
+ fame_object_t *object;
+
+ object = fame_get_object(fame_context, "profile/mpeg1");
+ if(object) fame_register(fame_context, "profile", object);
+
+ } else if(strcmp(config->readString("encoding_codec")->c_str(), "mpeg1") == 0) {
+ } else {
+ info->info("Using default (mpeg1) compression.");
+ }
+
+ fame_init(fame_context, &fame_par, fame_buffer, FAME_BUFFER_SIZE);
+}
+
+LibFAMEWrapper::~LibFAMEWrapper()
+{
+ delete [] yuv.y;
+ delete [] yuv.u;
+ delete [] yuv.v;
+}
+
+Frame *LibFAMEWrapper::encode(Frame *dvframe)
+{
+ // if(!f) return; // The file was not opened.
+
+ // Decode DV Frame to YUV422
+ int w = 720;
+ int h = 576;
+
+ unsigned char *pixels[3];
+ int pitches[3];
+
+ if(!dvdecoder) {
+ dvdecoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ dvdecoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(dvdecoder, dvframe->data);
+ //dv_parse_packs(decoder, frame->data); // Not needed anyway!
+
+ dvdecoder->system = e_dv_system_625_50; // PAL lines, PAL framerate
+ dvdecoder->sampling = e_dv_sample_422; // 4 bytes y, 2 bytes u, 2 bytes v
+ dvdecoder->std = e_dv_std_iec_61834;
+ dvdecoder->num_dif_seqs = 12;
+ }
+
+ pixels[ 0 ] = picture; // We use this as the output buffer
+ pitches[ 0 ] = w * 2;
+
+ dv_decode_full_frame(dvdecoder,
+ dvframe->data,
+ e_dv_color_yuv,
+ pixels,
+ pitches);
+
+ // Convert YUV422 to YUV420p
+ int w2 = w / 2;
+ uint8_t *y = yuv.y;
+ uint8_t *cb = yuv.u;
+ uint8_t *cr = yuv.v;
+ uint8_t *p = picture;
+
+ for ( int i = 0; i < h; i += 2 ) {
+ // process two scanlines (one from each field, interleaved)
+ for ( int j = 0; j < w2; j++ ) {
+ // packed YUV 422 is: Y[i] U[i] Y[i+1] V[i]
+ *( y++ ) = *( p++ );
+ *( cb++ ) = *( p++ );
+ *( y++ ) = *( p++ );
+ *( cr++ ) = *( p++ );
+ }
+
+ // process next two scanlines (one from each field, interleaved)
+ for ( int j = 0; j < w2; j++ ) {
+ // skip every second line for U and V
+ *( y++ ) = *( p++ );
+ p++;
+ *( y++ ) = *( p++ );
+ p++;
+ }
+ }
+
+ // Allocate a new frame for the output
+ Frame *output = new Frame(NULL, FAME_BUFFER_SIZE);
+
+ // Init frame params
+ dv_get_timestamp(dvdecoder, output->timecode); // Set timecode
+ output->size = 0; // Init size (incremented as we read)
+ unsigned char* pt = output->data; // Set pointer to start of data buffer
+
+ // Encode YUV frame and write it to disk.
+ fame_start_frame(fame_context, &yuv, 0);
+ int written;
+
+ while((written = fame_encode_slice(fame_context))) {
+ memcpy(pt, fame_buffer, written);
+ pt += written;
+ output->size += written;
+ }
+
+ // fame_frame_statistics_t stats;
+
+ // fame_end_frame(fame_context, &stats);
+ /*
+ info->info("frame_number: %d, coding: %c, target_bits: %d, actual_bits: %d, spatial_activity: %d, quant_scale: %f",
+ stats.frame_number,
+ stats.coding,
+ stats.target_bits,
+ stats.actual_bits,
+ stats.spatial_activity,
+ stats.quant_scale);
+ */
+ /*
+ fame_frame_statistics_t_ {
+ unsigned int frame_number;
+ char coding;
+ signed int target_bits;
+ unsigned int actual_bits;
+ unsigned int spatial_activity;
+ float quant_scale;
+ }
+ */
+ frame_number++;
+ calc_bitrate += output->size; //stats.actual_bits;
+ output->bitrate = (unsigned int)((double)calc_bitrate / (double)frame_number) * 25;
+
+ return output;
+}
+
diff --git a/server/libfame_wrapper.h b/server/libfame_wrapper.h
new file mode 100644
index 0000000..bf9e7b9
--- /dev/null
+++ b/server/libfame_wrapper.h
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libfame_wrapper.h
+ *
+ * Sat Jul 2 11:11:31 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_LIBFAME_WRAPPER_H__
+#define __MIAV_LIBFAME_WRAPPER_H__
+
+// Use libfame
+#include <fame.h>
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+#include "frame.h"
+#include "info.h"
+
+// size specifies the length of the buffer.
+#define FAME_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
+
+class LibFAMEWrapper {
+public:
+ LibFAMEWrapper(Info *info);
+ ~LibFAMEWrapper();
+
+ Frame *encode(Frame *dvframe);
+
+private:
+ unsigned long long calc_bitrate;
+ unsigned int frame_number;
+
+ Info* info;
+
+ // libFAME encoder
+ // unsigned char *fame_buffer;
+ fame_parameters_t fame_par;
+ fame_context_t *fame_context;
+ fame_yuv_t yuv;
+ unsigned char fame_buffer[FAME_BUFFER_SIZE];
+
+ // libdv decoder
+ dv_decoder_t *dvdecoder;
+
+ unsigned char picture[FAME_BUFFER_SIZE];
+};
+
+#endif/*__MIAV_LIBFAME_WRAPPER_H__*/
diff --git a/server/liblame_wrapper.cc b/server/liblame_wrapper.cc
new file mode 100644
index 0000000..5603d6f
--- /dev/null
+++ b/server/liblame_wrapper.cc
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * liblame_wrapper.cc
+ *
+ * Sat Jul 2 11:11: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 "liblame_wrapper.h"
+#include "miav_config.h"
+
+LibLAMEWrapper::LibLAMEWrapper(Info *i)
+{
+ info = i;
+
+ // Init library.
+ if( (gfp = lame_init()) == NULL) {
+ info->error("LAME initialization failed (due to malloc failure!)");
+ return;
+ }
+
+ lame_set_in_samplerate(gfp, INPUT_SAMPLE_RATE);
+ lame_set_out_samplerate(gfp, OUTPUT_SAMPLE_RATE);
+
+ lame_set_num_channels(gfp, CHANNELS);
+ // lame_set_num_samples(gfp, 1152);
+ // lame_set_num_samples(gfp, SAMPLES);
+ // lame_set_num_samples(gfp, 0);
+
+ lame_set_quality(gfp, config->readInt("mp3_quality"));
+ lame_set_mode(gfp, STEREO);
+ lame_set_brate(gfp, config->readInt("mp3_bitrate"));
+
+ lame_set_strict_ISO(gfp, 1);
+
+ // 1 = write a Xing VBR header frame.
+ lame_set_bWriteVbrTag(gfp, 0);
+
+ // Types of VBR. default = vbr_off = CBR
+ // lame_set_VBR(gfp, vbr_rh);
+
+ // VBR quality level. 0=highest 9=lowest
+ // lame_set_VBR_q(gfp, 6);
+
+ lame_set_copyright(gfp, 0); // is there a copyright on the encoded data?
+ lame_set_original(gfp, 1); // is the encoded data on the original media?
+ lame_set_error_protection(gfp, 0);// add 2 byte CRC protection to each frame?
+ lame_set_padding_type(gfp, PAD_NO); // PAD_NO, PAD_ALL, PAD_ADJUST, PAD_MAX_INDICATOR
+ // 0 = do not pad frames
+ // 1 = always pad frames
+ // 2 = adjust padding to satisfy bit rate
+ lame_set_extension(gfp, 0); // private extension bit
+
+
+ if (lame_init_params(gfp) < 0) {
+ info->error("LAME parameter initialization failed.");
+ return;
+ }
+
+ audio_buffer[0] = new int16_t[AUDIO_BUFFER_SIZE];
+ audio_buffer[1] = new int16_t[AUDIO_BUFFER_SIZE];
+
+ // And now for the dv decoder!
+ decoder = NULL;
+
+ calc_bitrate = 0;
+ frame_number = 0;
+}
+
+LibLAMEWrapper::~LibLAMEWrapper()
+{
+ delete audio_buffer[0];
+ delete audio_buffer[1];
+}
+
+Frame *LibLAMEWrapper::close(Frame *oldframe)
+{
+ Frame *frame;
+ unsigned int offset = 0;
+
+ frame = new Frame(NULL, (int)(1.25 * SAMPLES + 7200) * 2); // Big enough to hold two frames
+
+ if(oldframe) {
+ offset = oldframe->size;
+ frame->number = oldframe->number;
+ memcpy(frame->data, oldframe->data, oldframe->size);
+ delete oldframe;
+ }
+
+ int flush;
+
+ flush = lame_encode_finish(gfp, frame->data + offset, 7200);
+
+ frame->size = offset + flush;
+
+ calc_bitrate += flush;
+ frame->bitrate = (unsigned int)((double)calc_bitrate / (double)(frame_number)) * 25;
+
+ return frame;
+}
+
+#include <math.h>
+static unsigned int sin_cnt = 0;
+Frame *LibLAMEWrapper::encode(Frame *dvframe)
+{
+ if(dvframe->mute) {
+ // Overwrite audiobuffer with dummy data
+ double volume = 1000; // Min:= 0 - Max := 32000
+ double frequency = 440; // in Hz
+
+ for(int cnt = 0; cnt < SAMPLES; cnt++) {
+ sin_cnt++;
+ double sin_val = (((double)sin_cnt / (double)OUTPUT_SAMPLE_RATE) * (double)M_PI) * frequency;
+ audio_buffer[0][cnt] = audio_buffer[1][cnt] = (short int)(sin(sin_val) * volume);
+ }
+
+ // memset(audio_buffer[0], 0, sizeof(audio_buffer[0]));
+ // memset(audio_buffer[1], 0, sizeof(audio_buffer[1]));
+ } else {
+ // Decode audio from dv frame
+ if(!decoder) {
+ decoder = dv_decoder_new(FALSE/*this value is unused*/, FALSE, FALSE);
+ decoder->quality = DV_QUALITY_BEST;
+
+ dv_parse_header(decoder, dvframe->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;
+ }
+ // Decode audio using libdv
+ dv_decode_full_audio( decoder, dvframe->data, audio_buffer );
+ }
+
+ /**
+ * input pcm data, output (maybe) mp3 frames.
+ * This routine handles all buffering, resampling and filtering for you.
+ *
+ * The required mp3buf_size can be computed from num_samples,
+ * samplerate and encoding rate, but here is a worst case estimate:
+ *
+ * return code number of bytes output in mp3buffer. can be 0
+ * if return code = -1: mp3buffer was too small
+ *
+ * mp3buf_size in bytes = 1.25*num_samples + 7200
+ *
+ * I think a tighter bound could be: (mt, March 2000)
+ * MPEG1:
+ * num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
+ * MPEG2:
+ * num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
+ *
+ * but test first if you use that!
+ *
+ * set mp3buf_size = 0 and LAME will not check if mp3buf_size is
+ * large enough.
+ *
+ * NOTE:
+ * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels
+ * will be averaged into the L channel before encoding only the L channel
+ * This will overwrite the data in buffer_l[] and buffer_r[].
+ *
+ */
+ Frame* audio_frame = new Frame(NULL, (int)(1.25 * SAMPLES + 7200));
+
+ const short int *buffer_l = audio_buffer[0]; // PCM data for left channel
+ const short int *buffer_r = audio_buffer[1]; // PCM data for right channel
+ const int nsamples = SAMPLES; // number of samples per channel
+ unsigned char* mp3buf = audio_frame->data; // pointer to encoded MP3 stream
+ const int mp3buf_size = audio_frame->size; // number of valid octets in this
+
+ int val;
+ val = lame_encode_buffer(gfp, buffer_l, buffer_r, nsamples, mp3buf, mp3buf_size);
+ // val = lame_encode_mp3_frame(gfp, buffer_l, buffer_r, mp3buf, mp3buf_size);
+
+ // info->info("Framenr: %d", lame_get_frameNum(gfp));
+
+ if(val < 0) {
+ switch(val) {
+ case -1: // mp3buf was too small
+ info->error("Lame encoding failed, mp3buf was too small.");
+ break;
+ case -2: // malloc() problem
+ info->error("Lame encoding failed, due to malloc() problem.");
+ break;
+ case -3: // lame_init_params() not called
+ info->error("Lame encoding failed, lame_init_params() not called.");
+ break;
+ case -4: // psycho acoustic problems
+ info->error("Lame encoding failed, due to psycho acoustic problems.");
+ break;
+ default:
+ info->error("Lame encoding failed, due to unknown error.");
+ break;
+ }
+ }
+
+ /**
+ * OPTIONAL:
+ * lame_encode_flush_nogap will flush the internal mp3 buffers and pad
+ * the last frame with ancillary data so it is a complete mp3 frame.
+ *
+ * 'mp3buf' should be at least 7200 bytes long
+ * to hold all possible emitted data.
+ *
+ * After a call to this routine, the outputed mp3 data is complete, but
+ * you may continue to encode new PCM samples and write future mp3 data
+ * to a different file. The two mp3 files will play back with no gaps
+ * if they are concatenated together.
+ *
+ * This routine will NOT write id3v1 tags into the bitstream.
+ *
+ * return code = number of bytes output to mp3buf. Can be 0
+ */
+
+ int flush_sz = 0;
+
+ /*
+ flush_sz = lame_encode_flush_nogap(gfp, // global context handle
+ mp3buf + val, // pointer to encoded MP3 stream
+ mp3buf_size - val); // number of valid octets in this stream
+ */
+
+ // info->info("VAL: %d - FLUSH_SZ: %d - TOTAL: %d", val, flush_sz, (val + flush_sz));
+
+ audio_frame->size = val + flush_sz;
+
+ /*
+
+ int bitrate_kbps[14];
+ // lame_bitrate_kbps(gfp, bitrate_kbps);
+ lame_bitrate_hist(gfp, bitrate_kbps);
+ // 32 40 48 56 64 80 96 112 128 160 192 224 256 320
+ info->info("%d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ bitrate_kbps[0],
+ bitrate_kbps[1],
+ bitrate_kbps[2],
+ bitrate_kbps[3],
+ bitrate_kbps[4],
+ bitrate_kbps[5],
+ bitrate_kbps[6],
+ bitrate_kbps[7],
+ bitrate_kbps[8],
+ bitrate_kbps[9],
+ bitrate_kbps[10],
+ bitrate_kbps[11],
+ bitrate_kbps[12],
+ bitrate_kbps[13]);
+ */
+ // while(frame_number != lame_get_frameNum(gfp)) {
+
+ calc_bitrate += audio_frame->size;//lame_get_framesize(gfp);
+ frame_number ++;//= 1;//lame_get_frameNum(gfp);
+
+ // info->info("lame_get_frameNum(gfp) %d ?= frame_number %d", lame_get_frameNum(gfp), frame_number);
+ // }
+
+ // Bits pr. second
+ // 25 * 7 frames pr.second (it seems!)
+ audio_frame->bitrate = (unsigned int)((double)calc_bitrate / (double)(frame_number)) * 25;
+ /*
+ info->info("Audio size: %d, bitrate: %.4f",
+ audio_frame->bitrate,
+ (float)(config->readInt("mp3_bitrate") * 1000)/(float)(audio_frame->bitrate));
+ */
+
+ /*
+ FILE* fp = fopen("/tmp/audiotest.mp3", "a");
+ fwrite(audio_frame->data, audio_frame->size, 1, fp);
+ fclose(fp);
+ */
+ return audio_frame;
+}
diff --git a/server/liblame_wrapper.h b/server/liblame_wrapper.h
new file mode 100644
index 0000000..43518c8
--- /dev/null
+++ b/server/liblame_wrapper.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * liblame_wrapper.h
+ *
+ * Sat Jul 2 11:11: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_LIBLAME_WRAPPER_H__
+#define __MIAV_LIBLAME_WRAPPER_H__
+
+// Use libdv
+#include <libdv/dv.h>
+#include <libdv/dv_types.h>
+
+// Use liblame
+#include <lame/lame.h>
+
+#include "frame.h"
+#include "info.h"
+
+#define AUDIO_BUFFER_SIZE DV_AUDIO_MAX_SAMPLES
+
+#define CHANNELS 2
+#define INPUT_SAMPLE_RATE 48000
+#define OUTPUT_SAMPLE_RATE 48000
+#define SAMPLES OUTPUT_SAMPLE_RATE / 25
+
+class LibLAMEWrapper {
+public:
+ LibLAMEWrapper(Info *info);
+ ~LibLAMEWrapper();
+
+ Frame *encode(Frame *dvframe);
+
+ Frame *close(Frame *dvframe = NULL);
+
+private:
+ unsigned long long calc_bitrate;
+ int frame_number;
+
+ Info *info;
+
+ // LAME stuff
+ lame_global_flags *gfp;
+
+ // libdv stuff
+ dv_decoder_t *decoder;
+ int16_t *audio_buffer[2];
+};
+
+#endif/*__MIAV_LIBLAME_WRAPPER_H__*/
diff --git a/server/libmplex_wrapper.cc b/server/libmplex_wrapper.cc
new file mode 100644
index 0000000..4164ffe
--- /dev/null
+++ b/server/libmplex_wrapper.cc
@@ -0,0 +1,485 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libmplex_wrapper.cc
+ *
+ * Sun Oct 30 12:28:47 CET 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"
+#include "libmplex_wrapper.h"
+#include "miav_config.h"
+
+#ifdef WITH_LIBMPLEX
+
+#include <mjpeg_types.h>
+#include <mjpeg_logging.h>
+#include <mpegconsts.h>
+
+#include <mplex/interact.hpp>
+#include <mplex/bits.hpp>
+#include <mplex/outputstrm.hpp>
+#include <mplex/multiplexor.hpp>
+
+/**
+ * FrameOutputStream - Wraps the File object
+ */
+class FrameOutputStream : public OutputStream
+{
+public:
+ FrameOutputStream( Info *info, File *outputfile );
+ int Open( );
+ void Close();
+ off_t SegmentSize( );
+ void NextSegment();
+ void Write(uint8_t *data, unsigned int len);
+
+private:
+ Info *info;
+ off_t written;
+ File *file;
+};
+
+
+
+FrameOutputStream::FrameOutputStream( Info *info, File *outputfile )
+{
+ this->info = info;
+ file = outputfile;
+ written = 0;
+ info->info("FrameOutputStream - constructor");
+}
+
+int FrameOutputStream::Open()
+{
+ // info->info("FrameOutputStream::Open");
+ // Nothing to do here!
+ return 0;
+}
+
+void FrameOutputStream::Close()
+{
+ // info->info("FrameOutputStream::Close");
+ // Nothing to do here!
+}
+
+
+off_t FrameOutputStream::SegmentSize()
+{
+ // info->info("FrameOutputStream::SegmentSize - return: %d", written);
+ return written;
+
+ /*
+ struct stat stb;
+ fstat(fileno(strm), &stb);
+ off_t written = stb.st_size;
+ return written;
+ */
+}
+
+void FrameOutputStream::NextSegment( )
+{
+ // info->info("FrameOutputStream::NextSegment");
+ // Nothing to do here!
+ /*
+ auto_ptr<char> prev_filename_buf( new char[strlen(cur_filename)+1] );
+ char *prev_filename = prev_filename_buf.get();
+ fclose(strm);
+ ++segment_num;
+ strcpy( prev_filename, cur_filename );
+ snprintf( cur_filename, MAXPATHLEN, filename_pat, segment_num );
+ if( strcmp( prev_filename, cur_filename ) == 0 ) {
+ mjpeg_error_exit1("Need to split output but there appears to be no %%d in the filename pattern %s",
+ filename_pat );
+ }
+ strm = fopen( cur_filename, "wb" );
+ if( strm == NULL ) {
+ mjpeg_error_exit1( "Could not open for writing: %s", cur_filename );
+ }
+ */
+}
+
+void FrameOutputStream::Write( uint8_t *buf, unsigned int len )
+{
+ unsigned int write;
+ write = file->Write(buf, len);
+ written += write;
+ // info->info("FrameOutputStream::Write - len: %d", len);
+}
+
+/**
+ * FrameInputStream - Wraps the ThreadSafeQueuePriority objects, containing
+ * the prosessed frames from libfame and liblame.
+ */
+class FrameInputStream : public IBitStream
+{
+public:
+ FrameInputStream( Info *info, ThreadSafeQueuePriority *queue );
+ ~FrameInputStream();
+
+private:
+ Frame *getFrame();
+ size_t ReadStreamBytes( uint8_t *buf, size_t size );
+ bool EndOfStream();
+
+ Info *info;
+ ThreadSafeQueuePriority *queue;
+ bool seen_eof;
+ Frame *frame;
+ unsigned int read;
+};
+
+FrameInputStream::FrameInputStream( Info *info, ThreadSafeQueuePriority *queue ) :
+ IBitStream()
+{
+ this->info = info;
+ this->queue = queue;
+ seen_eof = false;
+ frame = NULL;
+ read = 0;
+ streamname = "MIaV Stream\0";
+
+ // info->info("FrameInputStream - constructor", seen_eof);
+
+ /*
+ if ((fileh = fopen(bs_filename, "rb")) == NULL)
+ {
+ mjpeg_error_exit1( "Unable to open file %s for reading.", bs_filename);
+ }
+ filename = strcpy( new char[strlen(bs_filename)+1], bs_filename );
+ streamname = filename;
+
+ SetBufSize(buf_size);
+ eobs = false;
+ byteidx = 0;
+ if (!ReadIntoBuffer())
+ {
+ if (buffered==0)
+ {
+ mjpeg_error_exit1( "Unable to read from %s.", bs_filename);
+ }
+ }
+ */
+ SetBufSize(BUFFER_SIZE);
+ // SetBufSize(buf_size);
+ eobs = false;
+ byteidx = 0;
+ if (!ReadIntoBuffer()) {
+ if (buffered==0) {
+ info->error( "Unable to read from %s.", streamname);
+ }
+ }
+
+ // info->info("FrameInputStream - leaving constructor", seen_eof);
+}
+
+
+/**
+ Destructor: close the device containing the bit stream after a read
+ process
+*/
+FrameInputStream::~FrameInputStream()
+{
+ // info->info("FrameInputStream - destructor", seen_eof);
+ // Nothing to do here!
+ /*
+ if (fileh)
+ {
+ fclose(fileh);
+ delete filename;
+ }
+ fileh = 0;
+ */
+ Release(); // Hmmm.. wonder what this 'Release()' does!?
+}
+
+Frame *FrameInputStream::getFrame()
+{
+ read = 0;
+ return queue->pop();
+}
+
+bool FrameInputStream::EndOfStream()
+{
+ // info->info("FrameInputStream::EndOfStream - return: %d", seen_eof);
+ return seen_eof;
+}
+
+size_t FrameInputStream::ReadStreamBytes( uint8_t *buf, size_t size )
+{
+ // info->info("FrameInputStream::ReadStreamBytes - size: %d", size);
+ unsigned int copied = 0;
+
+ while( copied < size ) {
+
+ // If we read the entire frame, prepare to get a new one
+ if(frame && read == frame->size) {
+ delete frame;
+ frame = NULL;
+ }
+
+ // If no frame is in the buffer, get one from the queue
+ if(frame == NULL) frame = getFrame();
+
+ // check for end of stream
+ if( frame->endOfFrameStream == true) {
+ seen_eof = true;
+ return copied;
+ }
+
+ // If a frame exists in the buffer copy it to the output buffer
+ // (No frame ocurres when *running is set to false)
+ if( frame ) {
+ unsigned int doread = (size - copied) < (frame->size - read) ?
+ size - copied : (frame->size - read);
+
+ //info->info("Requested: %d. Read: %d. Doread: %d. In buffer %d", size, (*read), doread, (*frame)->size);
+
+ memcpy(buf + copied, frame->data + read, doread);
+ read += doread;
+ copied += doread;
+ }
+ }
+
+ return copied;
+}
+
+/*******************************
+ *
+ * Command line job class - sets up a Multiplex Job based on command
+ * line and File I/O...
+ *
+ ******************************/
+
+class MIaVMultiplexJob : public MultiplexJob
+{
+public:
+ MIaVMultiplexJob(Info *info,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue);
+
+private:
+ bool ParseVideoOpt( const char *optarg );
+ bool ParseLpcmOpt( const char *optarg );
+};
+
+MIaVMultiplexJob::MIaVMultiplexJob(Info *info,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue) :
+ MultiplexJob()
+{
+ // this->info = info;
+ // info->info("MIaVMultiplexJob - constructor");
+ outfile_pattern = "/tmp/aaargh.mpg"; // Output file... or something
+
+ verbose = 0; // Level of verbosity. 0 = quiet, 1 = normal 2 = verbose/debug
+
+ VBR = config->readInt("video_bitrate") == 0; // Multiplex variable bit-rate video
+
+ always_system_headers = true; // Create System header in every pack in generic formats
+
+ // Specifies decoder buffers size in kB. [ 20...2000]
+ if( ! ParseVideoOpt( "500" ) )
+ info->error( "Illegal video decoder buffer size(s): %s", "500" );
+
+ // --lpcm-params | -L samppersec:chan:bits [, samppersec:chan:bits]
+ // if( ! ParseLpcmOpt( "48000:2:16" ) ) info->error( "Illegal LPCM option(s): %s", "48000:2:16" );
+
+ data_rate = 0; //Specify data rate of output stream in kbit/sec (default 0=Compute from source streams)
+ // Convert from kbit/sec (user spec) to 50B/sec units...
+ data_rate = (( data_rate * 1000 / 8 + 49) / 50 ) * 50;
+
+ audio_offset = 0; //Specify offset of timestamps (video-audio) in mSec
+ video_offset = 0; //Specify offset of timestamps (video-audio) in mSec
+
+ max_PTS = 0; // Multiplex only num seconds of material (default 0=multiplex all)
+
+ packets_per_pack = 5; //Number of packets per pack generic formats [1..100]
+
+ mux_format = 3; // Set defaults for particular MPEG profiles:
+ // 0 = Generic MPEG1
+ // 1 = VCD
+ // 2 = user-rate VCD
+ // 3 = Generic MPEG2
+ // 4 = SVCD
+ // 5 = user-rate SVCD
+ // 6 = VCD Stills
+ // 7 = SVCD Stills
+ // 8 = DVD with NAV sectors
+ // 9 = DVD
+
+ sector_size = 2042; // Specify sector size in bytes for generic formats [256..16384]
+
+ //max_segment_size = 0; // Maximum size of output file(s) in Mbyte (default: 0) (no limit)
+
+ multifile_segment = true; // Don't switch to a new output file if a sequence end marker
+ // is encountered ithe input video
+
+ (void)mjpeg_default_handler_verbosity(verbose);
+ info->info( "mplex version %s (%s %s)", VERSION,MPLEX_VER, MPLEX_DATE );
+
+ // Connect streams
+ vector<IBitStream *> inputs;
+ if(video_queue) inputs.push_back( new FrameInputStream( info, video_queue ) );
+ if(audio_queue) inputs.push_back( new FrameInputStream( info, audio_queue ) );
+ SetupInputStreams( inputs );
+}
+
+/*************************************************************************
+ Usage banner for the command line wrapper.
+*************************************************************************/
+/*
+ mjpegtools mplex-2 version VERSION ( MPLEX_VER )
+ Usage: %s [params] -o <output filename pattern> <input file>...
+ %%d in the output file name is by segment count
+ where possible params are:
+ --verbose|-v num
+ Level of verbosity. 0 = quiet, 1 = normal 2 = verbose/debug
+ --format|-f fmt
+ Set defaults for particular MPEG profiles
+ [0 = Generic MPEG1, 1 = VCD, 2 = user-rate VCD, 3 = Generic MPEG2,
+ 4 = SVCD, 5 = user-rate SVCD
+ 6 = VCD Stills, 7 = SVCD Stills, 8 = DVD with NAV sectors, 9 = DVD]
+ --mux-bitrate|-r num
+ Specify data rate of output stream in kbit/sec
+ (default 0=Compute from source streams)
+ --video-buffer|-b num [, num...]
+ Specifies decoder buffers size in kB. [ 20...2000]
+ --lpcm-params | -L samppersec:chan:bits [, samppersec:chan:bits]
+ --mux-limit|-l num
+ Multiplex only num seconds of material (default 0=multiplex all)
+ --sync-offset|-O num ms|s|mpt
+ Specify offset of timestamps (video-audio) in mSec
+ --sector-size|-s num
+ Specify sector size in bytes for generic formats [256..16384]
+ --vbr|-V
+ Multiplex variable bit-rate video
+ --packets-per-pack|-p num
+ Number of packets per pack generic formats [1..100]
+ --system-headers|-h
+ Create System header in every pack in generic formats
+ --max-segment-size|-S size
+ Maximum size of output file(s) in Mbyte (default: 0) (no limit)
+ --ignore-seqend-markers|-M
+ Don't switch to a new output file if a sequence end marker
+ is encountered ithe input video.
+ --workaround|-W workaround [, workaround ]
+ --help|-?
+ Print this lot out!
+*/
+
+
+bool MIaVMultiplexJob::ParseLpcmOpt( const char *optarg )
+{
+ char *endptr, *startptr;
+ unsigned int samples_sec;
+ unsigned int channels;
+ unsigned int bits_sample;
+ endptr = const_cast<char *>(optarg);
+ do {
+ startptr = endptr;
+ samples_sec = static_cast<unsigned int>(strtol(startptr, &endptr, 10));
+ if( startptr == endptr || *endptr != ':' )
+ return false;
+
+ startptr = endptr+1;
+ channels = static_cast<unsigned int>(strtol(startptr, &endptr, 10));
+ if(startptr == endptr || *endptr != ':' )
+ return false;
+
+ startptr = endptr+1;
+ bits_sample = static_cast<unsigned int>(strtol(startptr, &endptr, 10));
+ if( startptr == endptr )
+ return false;
+
+ LpcmParams *params = LpcmParams::Checked( samples_sec,
+ channels,
+ bits_sample );
+ if( params == 0 )
+ return false;
+ lpcm_param.push_back(params);
+ if( *endptr == ',' )
+ ++endptr;
+ } while( *endptr != '\0' );
+ return true;
+}
+
+bool MIaVMultiplexJob::ParseVideoOpt( const char *optarg )
+{
+ char *endptr, *startptr;
+ unsigned int buffer_size;
+ endptr = const_cast<char *>(optarg);
+ do
+ {
+ startptr = endptr;
+ buffer_size = static_cast<unsigned int>(strtol(startptr, &endptr, 10));
+ if( startptr == endptr )
+ return false;
+
+ VideoParams *params = VideoParams::Checked( buffer_size );
+ if( params == 0 )
+ return false;
+ video_param.push_back(params);
+ if( *endptr == ',' )
+ ++endptr;
+ }
+ while( *endptr != '\0' );
+ return true;
+}
+
+LibMPlexWrapper::LibMPlexWrapper(Info *info,
+ File *outputfile,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue)
+{
+ this->info = info;
+ this->outputfile = outputfile;
+ this->video_queue = video_queue;
+ this->audio_queue = audio_queue;
+}
+
+LibMPlexWrapper::~LibMPlexWrapper()
+{
+}
+
+
+void LibMPlexWrapper::multiplex()
+{
+ // info->info("MPLEX!");
+ // sleep(10);
+ // info->info("The road goes ever on and on...");
+ MIaVMultiplexJob job(info, video_queue, audio_queue);
+ FrameOutputStream output( info, outputfile );
+ Multiplexor mux(job, output);
+ mux.Multiplex();
+}
+
+
+#ifdef LIBMPLEX_WRAPPER_TEST
+int main (int argc, char* argv[])
+{
+ LibMPlexWrapper mplex;
+ mplex.multiplex();
+ return 0;
+}
+#endif/*LIBMPLEX_WRAPPER_TEST*/
+
+#endif/*WITH_LIBMPLEX*/
diff --git a/server/libmplex_wrapper.h b/server/libmplex_wrapper.h
new file mode 100644
index 0000000..1be71a1
--- /dev/null
+++ b/server/libmplex_wrapper.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * libmplex_wrapper.h
+ *
+ * Sun Oct 30 12:28:47 CET 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"
+#ifndef __MIAV_LIBMPLEX_WRAPPER_H__
+#define __MIAV_LIBMPLEX_WRAPPER_H__
+
+#ifdef WITH_LIBMPLEX
+
+#include "info.h"
+#include "file.h"
+#include "threadsafe_queue_priority.h"
+
+class LibMPlexWrapper {
+public:
+ LibMPlexWrapper(Info *info,
+ File *outputfile,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue);
+ ~LibMPlexWrapper();
+
+ void multiplex();
+
+private:
+ Info *info;
+ File *outputfile;
+ ThreadSafeQueuePriority *video_queue;
+ ThreadSafeQueuePriority *audio_queue;
+};
+#endif/*WITH_LIBMPLEX*/
+
+#endif/*__MIAV_LIBMPLEX_WRAPPER_H__*/
diff --git a/server/miav_daemon.cc b/server/miav_daemon.cc
new file mode 100644
index 0000000..500e92a
--- /dev/null
+++ b/server/miav_daemon.cc
@@ -0,0 +1,108 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_daemon.cc
+ *
+ * Thu Jun 9 11:14:19 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 "miav_daemon.h"
+
+#include "info_console.h"
+#include "miav_config.h"
+
+#include "server.h"
+#include "socket.h"
+
+#include <signal.h>
+#include <errno.h>
+
+MiavDaemon::MiavDaemon()
+{}
+
+MiavDaemon::~MiavDaemon()
+{}
+
+int MiavDaemon::daemon_main()
+{
+ MiavConfig cfg(ETC"/miav.conf", NULL);
+ InfoConsole info(&cfg);
+ config = new MiavConfig(ETC"/miav.conf", &info);
+
+ int port = config->readInt("server_port");
+ pid_t childpid; // variable to store the child's pid
+
+ signal(SIGCLD, SIG_IGN); // Ved SIGCHILD til IGNORE maa wait/waitpid ikke kaldes
+ // (ellers kommer der kernel-brok)
+
+ info.info("Starting MIaV server v. %s", VERSION);
+ info.info("Listening on port %d", port);
+ Socket *socket = new Socket(port, &info);
+
+ if(socket->hasError()) {
+ info.error("Listening socket has errors, quitting.");
+ delete socket;
+ return 1;
+ }
+
+ while(1) {
+ Socket *csocket = new Socket(socket->slisten());
+
+ if(socket->hasError()) {
+ info.error("Server socket has errors, quitting.");
+ delete csocket;
+ break;
+ }
+
+ if(csocket->hasError()) {
+ info.error("Child socket has errors, quitting.");
+ delete csocket;
+ break;
+ }
+
+ if(!csocket->isConnected()) {
+ info.error("Child socket is not connected, quitting.");
+ delete csocket;
+ break;
+ }
+
+ childpid = fork();
+
+ switch(childpid) {
+ case -1: // fork() returns -1 on failure
+ info.log("Fork error: %s", strerror(errno));
+ exit(1);
+ case 0: // fork() returns 0 to the child process
+ delete socket; // Close listen socket.
+ newConnection(csocket, &info);
+ delete csocket; // Close communication socket.
+ exit(0);
+
+ default: // fork() returns new pid to the parent process
+ break;
+ }
+ }
+
+ delete socket;
+ return 0;
+}
+
diff --git a/server/miav_daemon.h b/server/miav_daemon.h
new file mode 100644
index 0000000..6ab469e
--- /dev/null
+++ b/server/miav_daemon.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * miav_daemon.h
+ *
+ * Thu Jun 9 11:14:19 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_MIAV_DAEMON_H__
+#define __MIAV_MIAV_DAEMON_H__
+
+#include "daemon.h"
+
+class MiavDaemon: public Daemon {
+public:
+ MiavDaemon();
+ ~MiavDaemon();
+
+private:
+ int daemon_main();
+};
+
+#endif/*__MIAV_MIAV_DAEMON_H__*/
diff --git a/server/miav_server.cc b/server/miav_server.cc
new file mode 100644
index 0000000..88a0d2a
--- /dev/null
+++ b/server/miav_server.cc
@@ -0,0 +1,50 @@
+/* -*- 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_server.h"
+#include "miav_daemon.h"
+#include "miav_config.h"
+
+#include "info_console.h"
+
+#include <stdio.h>
+
+/**
+ * This function starts the MIaV server.
+ */
+int main(int argc, char *argv[])
+{
+ MiavDaemon daemon;
+
+ MiavConfig cfg(ETC"/miav.conf", NULL);
+
+ string *user = cfg.readString("server_user");
+ string *group = cfg.readString("server_group");
+
+ return daemon.run(user->c_str(), group->c_str());
+}
diff --git a/server/miav_server.h b/server/miav_server.h
new file mode 100644
index 0000000..ce7842a
--- /dev/null
+++ b/server/miav_server.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/server/mov_encoder.cc b/server/mov_encoder.cc
new file mode 100644
index 0000000..6ac5876
--- /dev/null
+++ b/server/mov_encoder.cc
@@ -0,0 +1,293 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder.cc
+ *
+ * Sat Feb 19 14:13:19 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 "mov_encoder.h"
+
+#include <errno.h>
+
+// For nice
+#include <unistd.h>
+
+#include "miav_config.h"
+
+#include "debug.h"
+#include "libfame_wrapper.h"
+
+MovEncoder::MovEncoder(volatile bool *r, sem_t *r_sem,
+ ThreadSafeQueueFIFO *in,
+ ThreadSafeQueuePriority *video_out,
+ ThreadSafeQueuePriority *audio_out,
+ Info *i)
+{
+ info = i;
+ info->info("MovEncoder");
+
+ running = r;
+
+ // Queues
+ inputqueue = in;
+ video_output_queue = video_out;
+ audio_output_queue = audio_out;
+
+ read_sem = r_sem;
+}
+
+MovEncoder::~MovEncoder()
+{
+ info->info("~MovEncoder");
+}
+
+
+// this runs in a thread
+void MovEncoder::thread_main()
+{
+ info->info("MovEncoder::run");
+
+ // Run with slightly lower priority than MovEncoderWriter AND AudioEncoder
+ nice(2);
+
+ FrameVector *item;
+ Frame *in_frame;
+ Frame *out_v_frame;
+ Frame *out_a_frame;
+
+ LibFAMEWrapper fame(info);
+
+ // Process until running == false and the queue is empty
+ while(*running) {
+
+ item = inputqueue->pop();
+
+ if(item) {
+ for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
+ in_frame = item->at(cnt);
+
+ // Check for end of stream
+ if(in_frame->endOfFrameStream == true) {
+ info->info("endOfFrameStream in MovEncoder");
+
+ // Signal to stop running
+ *running = false;
+
+ // Kick them sleepy ones so they get the message.
+ int threads = config->readInt("encoding_threads") - 1; // -1 cause we only need the others!
+ for(int cnt = 0; cnt < threads; cnt++) {
+ inputqueue->push(NULL);
+ }
+ }
+
+ // Encode video
+ out_v_frame = fame.encode(in_frame);
+ out_v_frame->number = in_frame->number;
+ out_v_frame->endOfFrameStream = in_frame->endOfFrameStream;
+
+ // Create audio frame
+ out_a_frame = in_frame;
+
+ video_output_queue->push(out_v_frame);
+ audio_output_queue->push(out_a_frame);
+ }
+
+ delete item;
+
+ item = NULL;
+
+ // Kick reader
+ sem_post(read_sem);
+ }
+ }
+
+ info->info("MovEncoder::stop");
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
+
+// this runs in a thread
+void MovEncoder::thread_main()
+{
+ info->info("MovEncoder::run");
+ // static volatile int test = 0;
+#ifndef NEW_QUEUE
+ int v_outsize = 0;
+ int a_outsize = 0;
+#endif
+ int insize = 0;
+
+ // Run with slightly lower priority than MovEncoderWriter AND AudioEncoder
+ nice(3);
+
+ FrameVector *item;
+ Frame *in_frame;
+ Frame *out_v_frame;
+ Frame *out_a_frame;
+
+ LibFAMEWrapper fame(info);
+
+ // Process until running == false and the queue is empty
+ while(*running) {
+ sem_wait(input_sem);
+
+ // Lock inout mutex
+ pthread_mutex_lock(input_mutex);
+ item = inputqueue->front();
+ inputqueue->pop();
+ insize = inputqueue->size();
+ pthread_mutex_unlock(input_mutex);
+ // Unlock input mutex
+
+ if(item) {
+ for(unsigned int cnt = 0; cnt < item->size(); cnt++) {
+ in_frame = item->at(cnt);
+
+ // Check for end of stream
+ if(in_frame->endOfFrameStream == true) {
+ info->info("endOfFrameStream in MovEncoder");
+
+ // Signal to stop running
+ *running = false;
+
+ // Kick them sleepy ones so they get the message.
+ int threads = config->readInt("encoding_threads");
+ for(int cnt = 0; cnt < threads; cnt++) sem_post(input_sem);
+ }
+ // Encode video
+ out_v_frame = fame.encode(in_frame);
+ out_v_frame->number = in_frame->number;
+ out_v_frame->endOfFrameStream = in_frame->endOfFrameStream;
+
+ // Create audio frame
+ out_a_frame = in_frame;
+
+#ifdef NEW_QUEUE
+ video_output_queue->push(out_v_frame);
+ audio_output_queue->push(out_a_frame);
+#else
+ // Lock output mutex
+ pthread_mutex_lock(video_output_mutex);
+ video_outputqueue->push(out_v_frame);
+ v_outsize = video_outputqueue->size();
+ pthread_mutex_unlock(video_output_mutex);
+ // Unlock output mutex
+
+ // Kick multiplexer (video)
+ sem_post(video_output_sem);
+
+ // Lock output mutex
+ pthread_mutex_lock(audio_output_mutex);
+ audio_outputqueue->push(out_a_frame);
+ a_outsize = audio_outputqueue->size();
+ pthread_mutex_unlock(audio_output_mutex);
+ // Unlock output mutex
+
+ // Kick audio encoder
+ sem_post(audio_output_sem);
+#endif
+ }
+
+ delete item;
+ item = NULL;
+
+ // Kick reader
+ sem_post(read_sem);
+ }
+ }
+
+ //info->info("Input pool size: %d, video output pool size: %d, audio output pool size: %d",
+ // insize, v_outsize, a_outsize);
+
+
+#ifndef NEW_QUEUE
+ // Kick audio encoder
+ sem_post(audio_output_sem);
+
+ // Kick multiplexer (video)
+ sem_post(video_output_sem);
+#endif
+
+ info->info("MovEncoder::stop");
+}
+*/
diff --git a/server/mov_encoder.h b/server/mov_encoder.h
new file mode 100644
index 0000000..8910f4b
--- /dev/null
+++ b/server/mov_encoder.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder.h
+ *
+ * Sat Feb 19 14:13:19 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 program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#include "config.h"
+#ifndef __RTVIDEOREC_ENCODER_H
+#define __RTVIDEOREC_ENCODER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <vector>
+using namespace std;
+
+#include "frame.h"
+#include "util.h"
+
+#include "thread.h"
+#include <pthread.h>
+
+#include "info.h"
+
+#include "threadsafe_queue_priority.h"
+#include "threadsafe_queue_fifo.h"
+
+class MovEncoder : public Thread {
+public:
+ MovEncoder(volatile bool *r, sem_t *r_sem,
+ ThreadSafeQueueFIFO *in,
+ ThreadSafeQueuePriority *video_out,
+ ThreadSafeQueuePriority *audio_out,
+ Info *info);
+ ~MovEncoder();
+
+ void thread_main();
+
+ volatile bool *running;
+
+private:
+ Info *info;
+
+ // Input queue
+ ThreadSafeQueueFIFO *inputqueue;
+
+ // Output queues
+ ThreadSafeQueuePriority *video_output_queue;
+ ThreadSafeQueuePriority *audio_output_queue;
+
+ // Reader (mov_encoder_thread.cc) semaphore
+ sem_t *read_sem;
+
+};
+
+#endif
+
diff --git a/server/mov_encoder_thread.cc b/server/mov_encoder_thread.cc
new file mode 100644
index 0000000..2ff013d
--- /dev/null
+++ b/server/mov_encoder_thread.cc
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_thread.cc
+ *
+ * Tue May 17 16:00:01 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 "mov_encoder_thread.h"
+#include <errno.h>
+#include "miav_config.h"
+
+MovEncoderThread::MovEncoderThread(const char *clientip, const char *cpr, Info *i)
+{
+ info = i;
+ info->info("MovEncoderThread");
+
+ // Queue
+ inputqueue = new ThreadSafeQueueFIFO();
+
+ // Initialize read semaphore
+ sem_init(&read_sem, 0, 0);
+
+ video_output_queue = new ThreadSafeQueuePriority(info);
+ audio_input_queue = new ThreadSafeQueuePriority(info);
+ audio_output_queue = new ThreadSafeQueuePriority(info);
+
+ info->info("video_output_queue: 0x%x", video_output_queue);
+ info->info("audio_input_queue: 0x%x", audio_input_queue);
+ info->info("audio_output_queue: 0x%x", audio_output_queue);
+
+ block = new FrameVector();
+
+ num_frames_in_block = config->readString("frame_sequence")->length();
+
+ info->info("Frame sequence length %d", num_frames_in_block);
+
+ threads = config->readInt("encoding_threads");
+
+ movencodersrunning = true;
+
+ for(int cnt = 0; cnt < threads; cnt++) sem_post(&read_sem);
+
+ // Create the video encoders
+ for(int cnt = 0; cnt < threads; cnt++) {
+ MovEncoder *movenc = new MovEncoder(&movencodersrunning, &read_sem,
+ inputqueue,
+ video_output_queue,
+ audio_input_queue,
+ info);
+ movenc->run();
+ encs.push_back(movenc);
+ }
+
+ // Create the audio encoder
+ audioenc = new AudioEncoder(audio_input_queue,
+ audio_output_queue,
+ info);
+ audioenc->run();
+
+ // Create the multiplexer
+ writer = new MovEncoderWriter(clientip, cpr,
+ video_output_queue,
+ audio_output_queue,
+ info);
+ writer->run();
+
+ frame_number = 0;
+}
+
+//#include <unistd.h>
+MovEncoderThread::~MovEncoderThread()
+{
+ info->info("~MovEncoderThread");
+
+ // First we destroy the movie encoders
+ for(int cnt = 0; cnt < threads; cnt++) {
+ encs[cnt]->wait_stop(); // Wait for it to stop
+ delete encs[cnt]; // Delete it
+ }
+ info->info("Deleted the movie encoders");
+
+
+ // Then we destroy the audio encoder
+ audioenc->wait_stop(); // Wait for it to stop.
+ delete audioenc; // delete the audio encoder
+ info->info("Deleted the audio encoder");
+
+
+ // Finally we destroy the writer.
+ writer->wait_stop(); // Wait for it to stop.
+ delete writer; // delete the writer (end thereby close the file)
+ info->info("Deleted the writer");
+
+
+ // Destroy the semaphore.
+ sem_destroy(&read_sem);
+
+ info->info("~MovEncoderThread::done");
+}
+
+static int output = 0;
+void MovEncoderThread::encode(Frame* frame)
+{
+ if(output % 250 == 0) // 25 * 24
+ info->info("inputqueue: %d\tvideo_outputqueue: %d\taudio_inputqueue: %d\taudio_outputqueue: %d.",
+ inputqueue->size(),
+ video_output_queue->size(),
+ audio_input_queue->size(),
+ audio_output_queue->size());
+ output++;
+
+ if(frame == NULL) {
+ info->info("MovEncoderThread::encode - NULL frame detected.");
+ // Terminate
+ return;
+ }
+
+ frame->number = frame_number;
+ block->push_back(frame);
+
+ // Switch frame
+ if(block->size() == num_frames_in_block || frame->endOfFrameStream == true) {
+ // Wait until a free encoder.
+ sem_wait(&read_sem);
+
+ inputqueue->push(block);
+
+ // Start new block
+ block = new FrameVector;
+ }
+
+ frame_number ++;
+}
+
+void MovEncoderThread::setSaveState(n_savestate savestate)
+{
+ writer->setSaveState(savestate);
+}
diff --git a/server/mov_encoder_thread.h b/server/mov_encoder_thread.h
new file mode 100644
index 0000000..feea8e2
--- /dev/null
+++ b/server/mov_encoder_thread.h
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_thread.h
+ *
+ * Tue May 17 16:00:01 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_MOV_ENCODER_THREAD_H__
+#define __MIAV_MOV_ENCODER_THREAD_H__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <vector>
+using namespace std;
+
+#include "frame.h"
+
+#include "threadsafe_queue_priority.h"
+#include "threadsafe_queue_fifo.h"
+
+#include "mov_encoder.h"
+#include "audio_encoder.h"
+#include "mov_encoder_writer.h"
+
+#include "info.h"
+
+// For savestate_n
+#include "package.h"
+
+class MovEncoderThread {
+public:
+ MovEncoderThread(const char *clientip, const char *cpr, Info *info);
+ ~MovEncoderThread();
+
+ void encode(Frame* frame);
+
+ void setSaveState(n_savestate savestate);
+
+private:
+ Info *info;
+
+ // FrameVectorQueue *inputqueue;
+ ThreadSafeQueueFIFO *inputqueue;
+ FrameVector *block;
+
+ //thread stuff
+ sem_t read_sem;
+
+ ThreadSafeQueuePriority *video_output_queue;
+ ThreadSafeQueuePriority *audio_input_queue;
+ ThreadSafeQueuePriority *audio_output_queue;
+
+ volatile bool movencodersrunning;
+
+ // Used for encoder switching
+ unsigned int frame_number;
+
+ unsigned int num_frames_in_block;
+
+ MovEncoderWriter *writer;
+ AudioEncoder* audioenc;
+
+ int threads;
+ vector<MovEncoder*> encs;
+ // vector<pthread_t*> tids;
+};
+
+#endif/*__MIAV_MOV_ENCODER_THREAD_H__*/
diff --git a/server/mov_encoder_writer.cc b/server/mov_encoder_writer.cc
new file mode 100644
index 0000000..1773527
--- /dev/null
+++ b/server/mov_encoder_writer.cc
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_writer.cc
+ *
+ * Sun May 22 12:51:36 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 "mov_encoder_writer.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <errno.h>
+
+#include <string>
+using namespace std;
+
+#include "miav_config.h"
+
+#include <time.h>
+
+#include "multiplexer.h"
+#include "libmplex_wrapper.h"
+
+#include "multicast_configuration.h"
+
+MovEncoderWriter::MovEncoderWriter(const char *clientip, const char* cpr,
+ ThreadSafeQueuePriority *video_q,
+ ThreadSafeQueuePriority *audio_q,
+ Info *i)
+{
+ info = i;
+ info->info("MovEncoderWriter");
+
+ // Create path and filename
+ char fname[256];
+ string *server_root;
+ char birthmonth[3];
+ char date[32];
+
+ // Get server root
+ server_root = config->readString("server_movie_root");
+
+ // Copy the bytes representing the birth month from the cpr
+ // [dd][mm][yy]-[nn][nn]
+ strncpy(birthmonth, &cpr[2], 2);
+ birthmonth[2] = 0;
+
+ // Create date (today) in [yyyy][mm][dd]
+ struct tm *ltime;
+ time_t t = time(NULL);
+ ltime = localtime(&t);
+ sprintf(date, "%.4d%.2d%.2d",
+ ltime->tm_year + 1900,
+ ltime->tm_mon + 1, // Ranging from 0 to 11
+ ltime->tm_mday);
+
+ sprintf(fname, "%s/%s/%s/%s-%s-", server_root->c_str(), birthmonth, cpr, cpr, date);
+
+ file = new File(fname, "mpg", info);
+
+ MulticastConfiguration mcconfig(info, ETC"/multicast.conf");
+
+ mcastconf_t mcclientconf = mcconfig.getConf((char*)clientip);
+
+ info->info("Client: %s - Enabled: %s - Addr: %s - Port: %d - WithAudio: %s",
+ mcclientconf.client.c_str(),
+ mcclientconf.enabled?"Yes\0":"No\0",
+ mcclientconf.addr.c_str(),
+ mcclientconf.port,
+ mcclientconf.with_audio?"Yes\0":"No\0");
+
+
+ multicast = NULL;
+ if(mcclientconf.enabled) multicast = new Multicast(info,
+ mcclientconf);
+
+ video_queue = video_q;
+ audio_queue = audio_q;
+
+ running = true;
+}
+
+MovEncoderWriter::~MovEncoderWriter()
+{
+ info->info("~MovEncoderWriter");
+ delete file;
+ if(multicast) delete multicast;
+}
+
+void MovEncoderWriter::thread_main()
+{
+ info->info("MovEncoderWriter::run");
+
+#ifdef WITH_LIBMPLEX
+ LibMPlexWrapper mplex(info,
+ file,
+ video_queue,
+ audio_queue);
+ mplex.multiplex();
+#else/*WITH_LIBMPLEX*/
+ Multiplexer multiplexer(file, multicast,
+ info, &running,
+ video_queue,
+ audio_queue);
+ multiplexer.multiplex();
+#endif/*WITH_LIBMPLEX*/
+
+ info->info("MovEncoderWriter::stop");
+}
+
+void MovEncoderWriter::setSaveState(n_savestate savestate)
+{
+ file->setSaveState(savestate);
+}
diff --git a/server/mov_encoder_writer.h b/server/mov_encoder_writer.h
new file mode 100644
index 0000000..ba9ff16
--- /dev/null
+++ b/server/mov_encoder_writer.h
@@ -0,0 +1,73 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * mov_encoder_writer.h
+ *
+ * Sun May 22 12:51:35 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_MOV_ENCODER_WRITER_H__
+#define __MIAV_MOV_ENCODER_WRITER_H__
+
+#include "frame.h"
+#include "thread.h"
+#include "file.h"
+#include "multicast.h"
+#include "info.h"
+
+#include "threadsafe_queue_priority.h"
+
+#include <string>
+using namespace std;
+
+// For n_savestate
+#include "package.h"
+
+#define AUDIO_FRAME(x) x->number%2==1
+#define VIDEO_FRAME(x) x->number%2==0
+
+class MovEncoderWriter : public Thread {
+public:
+ MovEncoderWriter(const char *clientip, const char* cpr,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue,
+ Info *info);
+ ~MovEncoderWriter();
+
+ void thread_main();
+
+ void setSaveState(n_savestate savestate);
+
+ volatile bool running;
+
+private:
+ Info *info;
+
+ File *file;
+ Multicast *multicast;
+
+ ThreadSafeQueuePriority *video_queue;
+ ThreadSafeQueuePriority *audio_queue;
+};
+
+
+#endif/*__MIAV_MOV_ENCODER_WRITER_H__*/
diff --git a/server/multicast.cc b/server/multicast.cc
new file mode 100644
index 0000000..0072c19
--- /dev/null
+++ b/server/multicast.cc
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast.cc
+ *
+ * Mon Sep 26 12:25:22 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"
+#include "multicast.h"
+
+#include "multicast_configuration.h"
+
+#include "miav_config.h"
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <sys/param.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+
+// For IP_MTU
+//#include <linux/in.h>
+//#ifndef IP_MTU
+//#define IP_MTU 14
+//#endif
+
+#include <errno.h>
+
+Multicast::Multicast(Info *i, mcastconf_t &mcclientconf)
+{
+ info = i;
+ udp_buffer = NULL;
+
+ multicast_audio = mcclientconf.with_audio;
+
+ // Open connection socket
+ if(!UDPOpen(mcclientconf.addr.c_str(), mcclientconf.port))
+ info->error("Error creating socket %s:%d",
+ mcclientconf.addr.c_str(),
+ mcclientconf.port);
+
+ int mtu = config->readInt("udp_packet_size");
+
+ // Create buffer with the size of MTU
+ // socklen_t mtu_sz;
+ // if(getsockopt(sock, SOL_IP, IP_MTU, &mtu, &mtu_sz) != -1) {
+
+ udp_buffer_size = mtu - 28;
+ if(udp_buffer_size < 1) udp_buffer_size = 1;
+ udp_buffer = new char[udp_buffer_size];
+ udp_buffer_pointer = udp_buffer;
+ info->info("UDP packet buffer size %db", udp_buffer_size);
+
+ //} else {
+ // info->error("Error getting MTU size from socket: %s", strerror(errno));
+ // return;
+ //}
+}
+
+Multicast::~Multicast()
+{
+ if(udp_buffer) delete udp_buffer;
+}
+
+int Multicast::Write(void* buf, int size)
+{
+ if(!udp_buffer) return 0; // no buffer to write in... better break out!
+
+ // info->info("To send: %d", size);
+
+ char *p = (char*)buf;
+ int left = udp_buffer_size - (udp_buffer_pointer - udp_buffer);
+
+ while(size) {
+ int to_copy = size > left ? left : size;
+
+ memcpy(udp_buffer_pointer, p, to_copy);
+
+ left-=to_copy;
+ udp_buffer_pointer += to_copy;
+
+ p+=to_copy;
+ size-=to_copy;
+
+ // info->info("Copied %d - %d to go", to_copy, size);
+
+ if(left == 0) {
+ // info->info("Sending full packet");
+ write(sock, udp_buffer, udp_buffer_size);
+ left = udp_buffer_size;
+ udp_buffer_pointer = udp_buffer;
+ }
+ }
+ return size;
+}
+
+bool Multicast::is_address_multicast(unsigned long address)
+{
+ if((address & 255) >= 224 && (address & 255) <= 239) {
+ info->info("Address is multicast.");
+ return true;
+ }
+ info->info("Address is NOT multicast.");
+ return false;
+}
+
+/*
+ * open UDP socket
+ */
+bool Multicast::UDPOpen(const char *address, int port)
+{
+ int enable = 1L;
+ struct sockaddr_in stAddr;
+ struct sockaddr_in stLclAddr;
+ struct hostent * host;
+ // int sock;
+
+ stAddr.sin_family = AF_INET;
+ stAddr.sin_port = htons(port);
+ if((host = gethostbyname(address)) == NULL) return false;
+ stAddr.sin_addr = *((struct in_addr *) host->h_addr_list[0]);
+
+ // Create a UDP socket
+ if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ return false;
+
+ // Allow multiple instance of the client to share the same address and port
+ if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &enable, sizeof(unsigned long int)) < 0)
+ return false;
+
+ // If the address is multicast, register to the multicast group
+ if(is_address_multicast(stAddr.sin_addr.s_addr)) {
+ struct ip_mreq stMreq;
+
+ // Bind the socket to port
+ stLclAddr.sin_family = AF_INET;
+ stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ stLclAddr.sin_port = stAddr.sin_port;
+ if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0) return false;
+
+ // Register to a multicast address
+ stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr;
+ stMreq.imr_interface.s_addr = INADDR_ANY;
+ if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) & stMreq, sizeof(stMreq)) < 0)
+ return false;
+ } else {
+ // Bind the socket to port
+ stLclAddr.sin_family = AF_INET;
+ stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+ stLclAddr.sin_port = htons(0);
+ if(bind(sock, (struct sockaddr*) & stLclAddr, sizeof(stLclAddr)) < 0)
+ return false;
+ }
+
+ connect(sock, (struct sockaddr*) & stAddr, sizeof(stAddr));
+
+ return true;
+}
diff --git a/server/multicast.h b/server/multicast.h
new file mode 100644
index 0000000..08df3e1
--- /dev/null
+++ b/server/multicast.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast.h
+ *
+ * Mon Sep 26 12:25:22 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"
+#ifndef __MIAV_MULTICAST_H__
+#define __MIAV_MULTICAST_H__
+
+#include "multicast_configuration.h"
+#include "info.h"
+
+class Multicast {
+public:
+ Multicast(Info *i, mcastconf_t &mcclientconf);
+ ~Multicast();
+
+ int Write(void* buf, int size);
+
+ bool multicast_audio;
+
+private:
+ Info *info;
+
+ bool is_address_multicast(unsigned long address);
+ bool UDPOpen(const char *address, int port);
+ int sock;
+
+ int udp_buffer_size;
+ char *udp_buffer;
+ char *udp_buffer_pointer;
+};
+
+#endif/*__MIAV_MULTICAST_H__*/
diff --git a/server/multicast_configuration.cc b/server/multicast_configuration.cc
new file mode 100644
index 0000000..969faca
--- /dev/null
+++ b/server/multicast_configuration.cc
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast_configuration.cc
+ *
+ * Wed Oct 12 10:12:11 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"
+#include "multicast_configuration.h"
+
+MulticastConfiguration::MulticastConfiguration(Info *info, char *file)
+ : MiavConfig(file, info)
+{
+ mcastconf_t conf;
+
+ // Create the default values.
+ global_conf.addr = "224.0.0.1";
+ global_conf.port = 1234;
+ global_conf.enabled = false;
+ global_conf.with_audio = false;
+
+ bool global = true;
+
+ _cfg *cfg = configs;
+
+ // Build the client list
+ while(cfg) {
+ if(strcmp(cfg->name->c_str(), "client") == 0) {
+ if(!global) confs.push_back(conf);
+
+ // Reset the configuration to the defaults
+ conf.client = *(cfg->stringval);
+ conf.addr = global_conf.addr;
+ conf.port = global_conf.port;
+ conf.enabled = global_conf.enabled;
+ conf.with_audio = global_conf.with_audio;
+
+ global = false;
+ }
+ if(strcmp(cfg->name->c_str(), "address") == 0) {
+ if(global) global_conf.addr = *(cfg->stringval);
+ else conf.addr = *(cfg->stringval);
+ }
+ if(strcmp(cfg->name->c_str(), "port") == 0) {
+ if(global) global_conf.port = cfg->intval;
+ else conf.port = cfg->intval;
+ }
+ if(strcmp(cfg->name->c_str(), "enabled") == 0) {
+ if(global) global_conf.enabled = cfg->boolval;
+ else conf.enabled = cfg->boolval;
+ }
+ if(strcmp(cfg->name->c_str(), "with_audio") == 0) {
+ if(global) global_conf.with_audio = cfg->boolval;
+ else conf.with_audio = cfg->boolval;
+ }
+ cfg = cfg->next;
+ }
+ if(!global) confs.push_back(conf);
+
+ // Show the configuration in the log file .
+ info->info("Global - Enabled: %s - Addr: %s - Port: %d - WithAudio: %s",
+ global_conf.enabled?"Yes\0":"No\0",
+ global_conf.addr.c_str(),
+ global_conf.port,
+ global_conf.with_audio?"Yes\0":"No\0");
+
+ for(unsigned int cnt = 0; cnt < confs.size(); cnt++) {
+ info->info("Client: %s - Enabled: %s - Addr: %s - Port: %d - WithAudio: %s",
+ confs[cnt].client.c_str(),
+ confs[cnt].enabled?"Yes\0":"No\0",
+ confs[cnt].addr.c_str(),
+ confs[cnt].port,
+ confs[cnt].with_audio?"Yes\0":"No\0");
+ }
+
+ info->info("Chosing:");
+}
+
+MulticastConfiguration::~MulticastConfiguration()
+{
+}
+
+mcastconf_t &MulticastConfiguration::getConf(char *client)
+{
+ for(unsigned int cnt = 0; cnt < confs.size(); cnt++) {
+ if(strcmp(confs[cnt].client.c_str(), client) == 0)
+ return confs[cnt];
+ }
+
+ return global_conf;
+}
+
+#ifdef __TEST_MULTICAST_CONFIGURATION
+#include "info_simple.h"
+
+int main(int argc, char *argv[]) {
+ if(argc < 2) {
+ fprintf(stderr, "usage:\n\t%s [filename]\n", argv[0]);
+ return 1;
+ }
+
+ InfoSimple info;
+ MulticastConfiguration conf(&info, argv[1]);
+
+ mcastconf_t mcconf = conf.getConf("192.168.0.11");
+
+ info.warn("Client: %s - Enabled: %s - Addr: %s - Port: %d",
+ mcconf.client.c_str(),
+ mcconf.enabled?"Yes\0":"No\0",
+ mcconf.addr.c_str(),
+ mcconf.port);
+
+ mcconf = conf.getConf("192.168.0.0");
+
+ info.warn("Client: %s - Enabled: %s - Addr: %s - Port: %d",
+ mcconf.client.c_str(),
+ mcconf.enabled?"Yes\0":"No\0",
+ mcconf.addr.c_str(),
+ mcconf.port);
+}
+
+#endif/* __TEST_MULTICAST_CONFIGURATION*/
diff --git a/server/multicast_configuration.h b/server/multicast_configuration.h
new file mode 100644
index 0000000..3fa7ef1
--- /dev/null
+++ b/server/multicast_configuration.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multicast_configuration.h
+ *
+ * Wed Oct 12 10:12:11 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"
+#ifndef __MIAV_MULTICAST_CONFIGURATION_H__
+#define __MIAV_MULTICAST_CONFIGURATION_H__
+
+#include "miav_config.h"
+
+#include <vector>
+#include <string>
+
+typedef struct {
+ std::string client;
+ std::string addr;
+ bool enabled;
+ int port;
+ bool with_audio;
+} mcastconf_t;
+
+class MulticastConfiguration : private MiavConfig {
+public:
+ MulticastConfiguration(Info *info, char *file);
+ ~MulticastConfiguration();
+
+ mcastconf_t &getConf(char *client);
+
+private:
+ std::vector<mcastconf_t> confs;
+ mcastconf_t global_conf;
+};
+
+#endif/*__MIAV_MULTICAST_CONFIGURATION_H__*/
diff --git a/server/multiplexer.cc b/server/multiplexer.cc
new file mode 100644
index 0000000..7a8b095
--- /dev/null
+++ b/server/multiplexer.cc
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multiplexer.cc
+ *
+ * Wed Aug 31 13:05:18 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"
+#include "multiplexer.h"
+
+#include <netinet/in.h>
+#include <math.h>
+
+#include "util.h"
+
+#define SIZEOF(x) (sizeof(x)-1)
+
+#define MASK3 0x7
+#define MASK15 0x7FFF
+#define TIMECODE32_30(x) ((x >> 30) & MASK3 )
+#define TIMECODE29_15(x) ((x >> 15) & MASK15)
+#define TIMECODE14_0(x) ((x >> 0) & MASK15)
+
+// Audio index lists
+/*
+static unsigned int frequency_index[4] = {44100, 48000, 32000, 0};
+//static unsigned int slots [4] = {12, 144, 0, 0};
+//static unsigned int slot_index [4] = {144, 144, 144, 0};
+//static unsigned int sample_index [4] = {384, 1152, 0, 0};
+static unsigned int bitrate_index [4][16] = {
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0}, // Reserved
+ {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0}, // Layer III
+ {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0}, // Layer II
+ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0} // Layer I
+};
+static char layer_index[4][12] = { "Reserved", "Layer III", "Layer II", "Layer I" };
+static char mode_index[4][32] = { "Stereo", "Joint Stereo", "Dual Channel", "Single Channel"};
+static char protection_index[2][32] = { "CRC check enabled", "CRC check disabled" };
+*/
+//static unsigned short int syncword = 0xFFF;
+
+// Video index lists
+/*
+#define FORBIDDEN -1.0
+#define RESERVED -2.0
+static double picture_rate_index[16] = {
+ FORBIDDEN, 23.976, 24.0, 25.0, 29.97, 30.0, 50.0, 59.94, 60,
+ RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED, RESERVED
+};
+*/
+Multiplexer::Multiplexer(File *f, Multicast *m, Info *i, volatile bool *r,
+ ThreadSafeQueuePriority *video_q,
+ ThreadSafeQueuePriority *audio_q)
+{
+ running = r;
+ file = f;
+ multicast = m;
+ info = i;
+
+ frame[TYPE_VIDEO] = NULL;
+ written[TYPE_VIDEO] = 0.0;
+
+ frame[TYPE_AUDIO] = NULL;
+ written[TYPE_AUDIO] = 0.0;
+
+ write_audio_packet = 0;
+ write_system_header = 0;
+
+ audio_header_read = false;
+
+ queue[TYPE_VIDEO] = video_q;
+ queue[TYPE_AUDIO] = audio_q;
+
+ SCR = 3904;//0x40010003LL;//0x1E80;
+
+}
+
+Multiplexer::~Multiplexer()
+{
+}
+
+int Multiplexer::Write(void* data, int size)
+{
+ int ret;
+
+ if(multicast && multicast->multicast_audio == true) multicast->Write(data, size);
+ ret = file->Write(data, size);
+
+ return ret;
+}
+
+int Multiplexer::Write(char* data, int size)
+{
+ return Write((void*)data, size);
+}
+
+int Multiplexer::Write(unsigned long long int val)
+{
+ int res;
+ int written = 0;
+ unsigned long int *h_u = (unsigned long int *)&val;
+ unsigned long int *h_l = (unsigned long int *)(((char*)&val) + sizeof(unsigned long int));
+
+ *h_u = htonl(*h_u);
+ *h_l = htonl(*h_l);
+
+ if((res = Write((void*)h_l, sizeof(*h_l))) < 0) {
+ return res;
+ }
+ written += res;
+
+ if((res = Write((void*)h_u, sizeof(*h_u))) < 0) {
+ return res;
+ }
+ written += res;
+
+ return written;
+}
+
+int Multiplexer::Write(long long int val)
+{
+ int res;
+ int written = 0;
+ unsigned long int *h_u = (unsigned long int *)&val;
+ unsigned long int *h_l = (unsigned long int *)(((char*)&val) + sizeof(unsigned long int));
+
+ *h_u = htonl(*h_u);
+ *h_l = htonl(*h_l);
+
+ if((res = Write((void*)h_l, sizeof(*h_l))) < 0) {
+ return res;
+ }
+ written += res;
+
+ if((res = Write((void*)h_u, sizeof(*h_u))) < 0) {
+ return res;
+ }
+ written += res;
+
+ return written;
+}
+
+int Multiplexer::Write(long int val)
+{
+ val = htonl(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+int Multiplexer::Write(unsigned long int val)
+{
+ val = htonl(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+int Multiplexer::Write(int val)
+{
+ val = htonl(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+int Multiplexer::Write(unsigned int val)
+{
+ val = htonl(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+int Multiplexer::Write(short int val)
+{
+ val = htons(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+int Multiplexer::Write(unsigned short int val)
+{
+ val = htons(val);
+
+ return Write((char*)&val, sizeof(val));
+}
+
+Frame *Multiplexer::getFrame(StreamType type)
+{
+ // info->info("Get %s Frame", type==TYPE_AUDIO?"Audio\0":"Video\0");
+
+ read[type] = 0;
+
+ Frame *frame = queue[type]->pop();
+
+ // If we multicast without audio, we better write the raw video stream.
+ if(type == TYPE_VIDEO && multicast && multicast->multicast_audio == false)
+ multicast->Write(frame->data, frame->size);
+
+ return frame;
+}
+
+int Multiplexer::read_stream(char *buf, unsigned int size, StreamType type)
+{
+ unsigned int copied = 0;
+
+ while( copied < size ) {
+
+ // If we read the entire frame, prepare to get a new one
+ if(frame[type] && read[type] == frame[type]->size) {
+ delete frame[type];
+ frame[type] = NULL;
+ }
+
+ // If no frame is in the buffer, get one from the queue
+ if(frame[type] == NULL) frame[type] = getFrame(type);
+
+ // check for end of stream
+ if( frame[type]->endOfFrameStream == true) {
+ info->info("endOfFrameStream in Multiplexer %s-stream.", type==TYPE_VIDEO?"video\0":"audio\0");
+ return copied;
+ }
+
+ // If a frame exists in the buffer copy it to the output buffer
+ // (No frame ocurres when *running is set to false)
+ if( frame[type] ) {
+ unsigned int doread = (size - copied) < (frame[type]->size - read[type]) ?
+ size - copied : (frame[type]->size - read[type]);
+
+ //info->info("Requested: %d. Read: %d. Doread: %d. In buffer %d", size, (*read), doread, (*frame)->size);
+
+ memcpy(buf + copied, frame[type]->data + read[type], doread);
+ read[type] += doread;
+ copied += doread;
+ }
+ }
+
+ return copied;
+}
+
+bool Multiplexer::packet(StreamType type)
+{
+ char buf[PACKET_SIZE];
+
+ // Write data
+ // info->info("\t\t[%sPacket]", type==TYPE_AUDIO?"Audio\0":"Video\0");
+
+ unsigned short int framesize = read_stream(buf, PACKET_SIZE, type);
+
+ Write((void*)ISO11172_1::packet_start_code_prefix, SIZEOF(ISO11172_1::packet_start_code_prefix));
+ switch(type) {
+ case TYPE_VIDEO:
+ Write((void*)ISO11172_1::stream_id_video1, SIZEOF(ISO11172_1::stream_id_video1));
+ break;
+ case TYPE_AUDIO:
+ Write((void*)ISO11172_1::stream_id_audio1, SIZEOF(ISO11172_1::stream_id_audio1));
+ break;
+ }
+
+ ISO11172_1::packet_header header;
+ header.marker_bit1 = header.marker_bit2 = header.marker_bit3 = 1;
+ header.padding = 0x2; // Must be 2
+ header.stuffing_byte = 0xFF;
+ header.packet_length = framesize + sizeof(ISO11172_1::packet_header) - sizeof(short);
+ header.system_clock_reference1 = TIMECODE32_30(SCR);
+ header.system_clock_reference2 = TIMECODE29_15(SCR);
+ header.system_clock_reference3 = TIMECODE14_0(SCR);
+ Write(*((unsigned long long int*)&header));
+
+ Write(buf, framesize);
+
+ if(framesize != PACKET_SIZE) return false;
+
+ written[type] += (double)PACKET_SIZE / (double)frame[type]->size;//bitrate;
+
+ return true;
+}
+
+/**
+ * Create and write a packet
+ */
+bool Multiplexer::packet()
+{
+ //info->info("\t\tWritten[A]: %f, Written[V]: %f", written[TYPE_AUDIO], written[TYPE_VIDEO]);
+
+ StreamType type;
+ /*
+ // New switching mechanism
+ if(written[TYPE_AUDIO] < written[TYPE_VIDEO]) {
+ type = TYPE_AUDIO;
+ } else {
+ type = TYPE_VIDEO;
+ }
+ */
+
+ // Newer switching mechanism
+ if(queue[TYPE_AUDIO]->size() > queue[TYPE_VIDEO]->size()) {
+ type = TYPE_AUDIO;
+ } else {
+ type = TYPE_VIDEO;
+ }
+
+
+ if(!packet(type)) {
+ // Flush the other stream too...
+ if(type == TYPE_AUDIO) type = TYPE_VIDEO;
+ else type = TYPE_AUDIO;
+ while(packet(type));
+ return false;
+ }
+ return true;
+
+ /*
+ // Count this up here, we want audio packets in packet 4, 9, ... NOT 0, 3, ...
+
+ write_audio_packet++;
+ if(write_audio_packet % AUDIO_PACKET_FREQUENCY == 0) {
+ packet(TYPE_AUDIO);
+ } else {
+ packet(TYPE_VIDEO);
+ }
+ */
+}
+
+/**
+ * Create and write the system header
+ */
+void Multiplexer::system_header()
+{
+ // info->info("\t\t[System Header]");
+
+ // system_header_start_code (32 bits)
+ Write((void*)ISO11172_1::system_header_start_code, SIZEOF(ISO11172_1::system_header_start_code));
+
+ ISO11172_1::system_header header;
+
+ header.marker_bit1 = header.marker_bit2 = header.marker_bit3 = 1;
+
+ header.header_length = 8 - 2 + (NUM_TYPES * 3);
+ // (sizeof(header) - sizeof(header.header_length)) +
+ // NUM_TYPES * sizeof(ISO11172_1::stream_description);
+ header.rate_bound = 3521; // FIXME: Taken from the example!
+ header.audio_bound = 1; // Only 1 audio stream
+ header.fixed_flag = 1; // Fixed bitrate (0 indicates vbr)
+ header.CSPS_flag = 1; // Standarts compliant? (yes: see lame_set_strict_ISO in liblame_wrapper.cc)
+ header.system_audio_clock_flag = 1; // FIXME: What excactly is this??
+ header.system_video_clock_flag = 1; // FIXME: What excactly is this??
+ header.video_bound = 1; // Only 1 video stream
+ header.reserved_byte = 0xFF; // Must be 0xFF
+ Write(*((unsigned long long int*)&header));
+
+ ISO11172_1::stream_description audio_stream_description;
+ audio_stream_description.stream_id = 0xC0;
+ audio_stream_description.market_bits = 0x3;
+ audio_stream_description.STD_buffer_bound_scale = 0; // Must be 0 for audio streams
+ audio_stream_description.STD_buffer_size_bound = 32; // Buffer must be 32 * 128 bytes
+ Write(*((unsigned long int*)&audio_stream_description));
+
+ ISO11172_1::stream_description video_stream_description;
+ video_stream_description.stream_id = 0xE3;
+ video_stream_description.market_bits = 0x3;
+ video_stream_description.STD_buffer_bound_scale = 1; // Must be 1 for video streams
+ video_stream_description.STD_buffer_size_bound = 46; // Buffer must be 32 * 1024 bytes
+ Write(*((unsigned long int*)&video_stream_description));
+}
+
+/**
+ * Create and write a pack
+ */
+bool Multiplexer::pack()
+{
+ // info->info("\t[Pack");
+
+ Write((void*)ISO11172_1::pack_start_code, SIZEOF(ISO11172_1::pack_start_code));
+
+ ISO11172_1::pack_header header;
+ // Set marker bits to 1
+ header.marker_bit1 =
+ header.marker_bit2 =
+ header.marker_bit3 =
+ header.marker_bit4 =
+ header.marker_bit5 = 1;
+
+ header.padding = 0x2;
+
+ unsigned int video_data_rate;
+ unsigned int audio_data_rate;
+
+ if(frame[TYPE_AUDIO]) audio_data_rate = frame[TYPE_AUDIO]->bitrate;
+ else audio_data_rate = 112000;
+
+ if(frame[TYPE_VIDEO]) video_data_rate = frame[TYPE_VIDEO]->bitrate;
+ else video_data_rate = 1100000;
+
+ unsigned int Rmux = ISO11172_1::Rmux(video_data_rate,
+ audio_data_rate,
+ 20, // packet_header_size,
+ 12, // pack_header_size,
+ PACKETS_PER_PACK, // packets_per_pack,
+ PACKET_SIZE);// packet_data_size)
+
+ header.mux_rate = Rmux;
+ //0x1B82;
+
+ SCR = ISO11172_1::SCR(SCR,
+ 12, //pack_header_size,
+ PACKETS_PER_PACK, //packets_per_pack,
+ PACKET_SIZE, //packet_data_size,
+ Rmux);
+
+ // SCR = 0x40010003LL;
+
+ header.system_clock_reference1 = TIMECODE32_30(SCR);
+ header.system_clock_reference2 = TIMECODE29_15(SCR);
+ header.system_clock_reference3 = TIMECODE14_0(SCR);
+ /*
+ info->info("timecode All: %lld, 1: %lld, 2: %lld, 3: %lld",
+ SCR,
+ (unsigned long long int)header.system_clock_reference1,
+ (unsigned long long int)header.system_clock_reference2,
+ (unsigned long long int)header.system_clock_reference3
+ );
+ */
+ Write(*((unsigned long long int*)&header));
+
+ if(write_system_header % SYSTEM_HEADER_FREQUENCY == 0) system_header();
+ // Count this up here, we want a system header in pack 0, 5, ... NOT 4, 9, ...
+ write_system_header++;
+
+ for(int cnt = 0; cnt < PACKETS_PER_PACK; cnt++)
+ if(!packet()) return false;
+
+ // info->info("\t]");
+
+ return true;
+}
+
+/**
+ *
+ */
+void Multiplexer::iso11172_stream()
+{
+ // info->info("[iso11172_stream");
+
+ while(pack());
+
+ // info->info("]");
+ // info->info("[iso11172_end_code]");
+ Write((void*)ISO11172_1::end_code, SIZEOF(ISO11172_1::end_code));
+
+ /*
+ info->info("false && false = %d", false && false);
+ info->info("true && false = %d", true && false);
+ info->info("true && true = %d", true && true);
+ */
+}
+
+//#define BYPASS TYPE_VIDEO
+//#define BYPASS TYPE_AUDIO
+void Multiplexer::multiplex()
+{
+#ifdef BYPASS
+
+ int frmsz;
+ char buf[1024];
+ do {
+ frmsz = read_stream(buf, sizeof(buf), BYPASS);
+ info->info("Wrote %d bytes", frmsz);
+ Write(buf, frmsz);
+ } while(frmsz == sizeof(buf));
+ return;
+
+#else/*BYPASS*/
+
+ iso11172_stream();
+
+#endif/*BYPASS*/
+}
diff --git a/server/multiplexer.h b/server/multiplexer.h
new file mode 100644
index 0000000..9959009
--- /dev/null
+++ b/server/multiplexer.h
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * multiplexer.h
+ *
+ * Wed Aug 31 13:05:18 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"
+#ifndef __MIAV_MULTIPLEXER_H__
+#define __MIAV_MULTIPLEXER_H__
+
+#include "iso11172-1.h"
+#include "iso11172-2.h"
+#include "iso11172-3.h"
+
+#include "file.h"
+#include "multicast.h"
+#include "info.h"
+#include "frame.h"
+
+#include "threadsafe_queue_priority.h"
+
+/**
+ * Multiplexer configuration
+ */
+// How many packets should we put in one pack
+#define PACKETS_PER_PACK 3
+
+// How many packets bewteen audio packs
+#define AUDIO_PACKET_FREQUENCY 10
+
+// How many packs bewteen system headers
+#define SYSTEM_HEADER_FREQUENCY 5
+
+// Size of video or audio data pr. packet
+#define PACKET_SIZE 2028
+
+/**
+ * Other stuff
+ */
+// The number of streamtypes.
+#define NUM_TYPES 2
+
+// Enum of the streamtypes.
+typedef enum {
+ TYPE_VIDEO,
+ TYPE_AUDIO
+} StreamType;
+
+
+class Multiplexer {
+public:
+ Multiplexer(File *file, Multicast *m, Info *info, volatile bool *running,
+ ThreadSafeQueuePriority *video_queue,
+ ThreadSafeQueuePriority *audio_queue);
+ ~Multiplexer();
+
+ void multiplex();
+
+private:
+ int Write(void* data, int size);
+ int Write(char* data, int size);
+ int Write(unsigned long long int val);
+ int Write(long long int val);
+ int Write(long int val);
+ int Write(unsigned long int val);
+ int Write(int val);
+ int Write(unsigned int val);
+ int Write(short int val);
+ int Write(unsigned short int val);
+
+ unsigned long long int SCR;
+
+ double written[NUM_TYPES];
+
+ void iso11172_stream();
+ bool pack();
+ void system_header();
+ bool packet();
+ bool packet(StreamType type);
+ /*
+ void audio_packet();
+ void video_packet();
+
+ void audio_data(ISO11172_3::header *header);
+ void audio_data_layer_I(ISO11172_3::header *header);
+ void audio_data_layer_II(ISO11172_3::header *header);
+ void audio_data_layer_III(ISO11172_3::header *header);
+
+ void video_data(ISO11172_2::sequence_header_1 *header1,
+ ISO11172_2::sequence_header_2 *header2);
+ */
+ // Frequency variables
+ unsigned int write_system_header;
+ unsigned int write_audio_packet;
+
+ Frame *getFrame(StreamType type);
+ int read_stream(char *buf, unsigned int size, StreamType type);
+
+ Frame *frame[NUM_TYPES];
+ unsigned int frame_number[NUM_TYPES];
+ unsigned int read[NUM_TYPES];
+
+ File *file;
+ Multicast *multicast;
+ Info *info;
+ volatile bool *running;
+
+ // Audio Header
+ bool audio_header_read;
+
+ ThreadSafeQueuePriority *queue[NUM_TYPES];
+};
+
+#endif/*__MIAV_MULTIPLEXER_H__*/
diff --git a/server/server.cc b/server/server.cc
new file mode 100644
index 0000000..34aac7b
--- /dev/null
+++ b/server/server.cc
@@ -0,0 +1,136 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.cc
+ *
+ * Mon Nov 8 11:35:01 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 "server.h"
+#include "miav.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// For mkdir
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// For unlink
+#include <unistd.h>
+
+// For errno
+#include <errno.h>
+
+// For inet_ntoa
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "miav_config.h"
+
+#include "mov_encoder_thread.h"
+#include "img_encoder.h"
+
+#include "server_status.h"
+
+#include "dv.h"
+
+void newConnection(Socket *socket, Info *info)
+{
+ char cpr[256];
+ char clientip[64];
+ bool hasCpr = false;
+ ServerStatus status(info);
+
+ n_savestate savestate = LATER;
+ n_header h;
+ Frame *frame;
+ Frame *freeze_frame = NULL;
+ MovEncoderThread *enc = NULL;
+
+ frame = new Frame(NULL, DVPACKAGE_SIZE);
+
+ info->info("CONNECTION OPENED");
+ info->info("New connection (%s)", inet_ntoa(socket->socketaddr.sin_addr));
+
+ sprintf(clientip, "%s", inet_ntoa(socket->socketaddr.sin_addr));
+
+ Network network = Network(socket, info);
+ while(int ret = network.recvPackage(&h, frame->data, frame->size)) {
+ status.checkPoint();
+
+ if(ret == -1) {
+ info->error("A network error ocurred, terminating session");
+ break;
+ }
+
+ frame->mute = h.header.h_data.mute;
+
+ if(!hasCpr) {
+ sprintf(cpr, h.header.h_data.cpr);
+ hasCpr = true;
+ }
+
+ if(h.header.h_data.snapshot) {
+ if(freeze_frame) {
+ ImgEncoder(cpr, info).encode(freeze_frame, 100);
+ delete freeze_frame;
+ freeze_frame = NULL;
+ } else {
+ ImgEncoder(cpr, info).encode(frame, 100);
+ }
+ }
+
+ if(h.header.h_data.savestate != NO_CHANGE) {
+ savestate = h.header.h_data.savestate;
+ info->info("GOT SAVESTATE FROM NETWORK: %d", savestate );
+ }
+
+ if(h.header.h_data.freeze) {
+ if(freeze_frame) delete freeze_frame;
+ // copy the frame into another temporary one.
+ freeze_frame = new Frame(frame->data, frame->size);
+ }
+
+ // This one must be last!
+ if(h.header.h_data.record) {
+ // if(!enc) enc = newMovEncoder(cpr);
+ if(!enc) enc = new MovEncoderThread(clientip, cpr, info);
+ enc->encode(frame);
+ }
+
+ frame = new Frame(NULL, DVPACKAGE_SIZE);
+ }
+
+ info->info("Closing connection...");
+
+ // No encoder exists, if this is a pure snapshot (image) connection.
+ if(enc) {
+ enc->setSaveState(savestate);
+ // Send end of stream frame.
+ frame->endOfFrameStream = true;
+ enc->encode(frame);
+ delete enc;
+ }
+
+ info->info("CONNECTION CLOSED");
+}
diff --git a/server/server.h b/server/server.h
new file mode 100644
index 0000000..7126a75
--- /dev/null
+++ b/server/server.h
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server.h
+ *
+ * Mon Nov 8 11:35:01 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.
+ */
+#ifndef __SERVER_H__
+#define __SERVER_H__
+
+#include "socket.h"
+
+#include "info.h"
+
+void newConnection(Socket *s, Info* info);
+
+
+#endif/*__SERVER_H__*/
diff --git a/server/server_status.cc b/server/server_status.cc
new file mode 100644
index 0000000..7f4714e
--- /dev/null
+++ b/server/server_status.cc
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server_status.cc
+ *
+ * Fri Apr 29 13:58:26 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 "server_status.h"
+
+#include <stdio.h>
+
+ServerStatus::ServerStatus(Info *i)
+{
+ info = i;
+
+ gettimeofday(&oldtime, NULL);
+
+ for(int cnt = 0; cnt < BUFFERSIZE; cnt++) {
+ frametime[cnt] = 41660;
+ }
+
+ gettimeofday(&time, NULL);
+
+ interval = 0;
+}
+
+ServerStatus::~ServerStatus()
+{
+}
+
+void ServerStatus::checkPoint()
+{
+ for(int cnt = BUFFERSIZE - 1; cnt > 0; cnt--) {
+ frametime[cnt] = frametime[cnt-1];
+ }
+ frametime[0] = (1000000 * time.tv_sec + time.tv_usec) - (1000000 * oldtime.tv_sec + oldtime.tv_usec);
+
+ oldtime.tv_sec = time.tv_sec;
+ oldtime.tv_usec = time.tv_usec;
+
+ gettimeofday(&time, NULL);
+
+ interval += frametime[0];
+ if(interval > UPD) {
+ interval = 0;
+ double total = 0.0;
+ for(int cnt = 0; cnt < BUFFERSIZE; cnt++) {
+ total += (double)frametime[cnt];
+ }
+ info->info("Status - fps: %f", 1000000.0 / (total / (double)BUFFERSIZE));
+ }
+
+}
+
+/*
+date(1), gettimeofday(2), ctime(3), ftime(3)
+*/
diff --git a/server/server_status.h b/server/server_status.h
new file mode 100644
index 0000000..5a7cb6c
--- /dev/null
+++ b/server/server_status.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ * server_status.h
+ *
+ * Fri Apr 29 13:58:26 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_SERVER_STATUS_H__
+#define __MIAV_SERVER_STATUS_H__
+
+#include "info.h"
+
+#include <sys/time.h>
+
+// How many steps to do avarage calculation over.
+#define BUFFERSIZE 100
+
+// Interval in us (microseconds)
+#define UPD 60 * 1000 * 1000 // 1 minute
+
+class ServerStatus {
+public:
+ ServerStatus(Info *info);
+ ~ServerStatus();
+
+ void checkPoint();
+
+private:
+ long long interval;
+ Info *info;
+ unsigned int frametime[BUFFERSIZE];
+ struct timeval time;
+ struct timeval oldtime;
+};
+
+#endif/*__MIAV_SERVER_STATUS_H__*/