summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO64
-rw-r--r--src/camera.cc4
-rw-r--r--src/camera.h3
-rw-r--r--src/encoder.cc9
-rw-r--r--src/encoder.h4
-rw-r--r--src/img_encoder.h14
-rw-r--r--src/mainwindow.cc75
-rw-r--r--src/mainwindow.h9
-rw-r--r--src/messagebox.cc41
-rw-r--r--src/messagebox.h9
-rw-r--r--src/miav.conf14
-rw-r--r--src/package.h8
-rw-r--r--src/server.cc25
-rw-r--r--src/util.h3
14 files changed, 230 insertions, 52 deletions
diff --git a/TODO b/TODO
index 1bbef10..7e9ff73 100644
--- a/TODO
+++ b/TODO
@@ -16,9 +16,10 @@ Mainwindow:
[x] - Make generic gui layout code.
[x] - Make icons.
[x] - Make statusbar.
- [ ] - Make flashing record bar.
- [ ] - Show network connection in statusbar.
- [ ] - Show camera connection in statusbar.
+ [x] - Make flashing record bar.
+ [ ] - Show network connection status in statusbar.
+ [ ] - Show camera connection status in statusbar.
+ [x] - Save movie messagebox (yes/no/dunno)
[ ] - Test it.
CPRQueryDialog:
@@ -30,6 +31,10 @@ CPRQueryDialog:
[ ] - Make icons?
[ ] - Test it.
+Encoder:
+ [ ] - Send savestate signal.
+ [ ] - Make all data sent before deleting network object. (flush)
+
Decoder:
[ ] - Enable sound decoding for the network stream.
@@ -47,6 +52,9 @@ ImgEncoder:
MovEncoder:
[ ] - Enable sound.
+Main:
+ [ ] - Save movie signal handling.
+
==========================================================================
TASKS (common)
==========================================================================
@@ -85,4 +93,52 @@ Destructor:
- Cleanup
getNextFrame:
- - returns: AVframe pointer \ No newline at end of file
+ - returns: AVframe pointer
+
+==========================================================================
+ SAVE THE MOVIE?
+==========================================================================
+When the stop button is clicked, a msg box pops up, "Save? [yes, no, dunno]"
+network connection is no killed before this has been answered, and an empty
+frame has been send to the server with the answer.
+
+On the serverside, a variable describing wether the file is to be saved (SAVE),
+deleted (DELETE), og scheduled for later descision (LATER).
+
+It is initialized with LATER, in order to prevent errors due to a malfunction
+leading to a disconnection.
+
+If a flag is recieved, the state is overwritten.
+
+If the state is SAVE, when the connection is terminated, the file is moved to
+a folder containing permanent data store.
+
+If the state is DELETE, the file is moved to a folder containing files scheduled
+for deletion, when more space is needed (no files are removed at this point)
+
+If the state is LATER, the file is moved to a folder containing files with this
+purpose.
+
+A cron job examines this folder regularly (test how often).
+If a file has been here for more than a week, the administrator is contacted by
+email.
+
+==========================================================================
+ Semphores and mutexes in the client network architechture
+==========================================================================
+,-----------.
+| DV stream |
+`-----------'
+ |
+ V
+,-----------.
+| Decoder |
+`-----------'
+ | \
+ V \
+,-----------. \
+| Player | \
+`-----------' \
+ \ ,-----------.
+ ->| Encoder |
+ `-----------'
diff --git a/src/camera.cc b/src/camera.cc
index 9e9fd82..772d48a 100644
--- a/src/camera.cc
+++ b/src/camera.cc
@@ -146,9 +146,9 @@ void Camera::start()
else errorstatus->pushError("Camera not initialized.");
}
-void Camera::stop()
+void Camera::stop(n_savestate save)
{
- if(initialized) encoder->stop();
+ if(initialized) encoder->stop(save);
else errorstatus->pushError("Camera not initialized.");
}
diff --git a/src/camera.h b/src/camera.h
index 25e1972..e5b4cee 100644
--- a/src/camera.h
+++ b/src/camera.h
@@ -43,6 +43,7 @@ using namespace std;
#include "decoder.h"
#include "encoder.h"
#include "player.h"
+#include "package.h"
#include "thread.h"
#include "ffframe.h"
@@ -65,7 +66,7 @@ public:
// Camera actions
void start();
- void stop();
+ void stop(n_savestate save);
void freeze();
void unfreeze();
void snapshot();
diff --git a/src/encoder.cc b/src/encoder.cc
index 3a4ade2..ca8fb4f 100644
--- a/src/encoder.cc
+++ b/src/encoder.cc
@@ -69,18 +69,14 @@ Encoder::~Encoder()
void Encoder::encode()
{
DVFrame *f;
- printf("0\n");
while(*running) {
- printf("1\n");
sem_wait(sem);
- printf("2\n");
pthread_mutex_lock(mutex);
f = queue->pop();
pthread_mutex_unlock(mutex);
- printf("3\n");
if((f && record) ||
(freeze_request != freeze_value) ||
(shoot_request != shoot_value)) {
@@ -91,6 +87,7 @@ void Encoder::encode()
h.header.h_data.freeze = (freeze_request != freeze_value);
h.header.h_data.snapshot = (shoot_request != shoot_value);
h.header.h_data.record = record;
+ h.header.h_data.savestate = NO_CHANGE;
if(freeze_request != freeze_value) freeze_value = freeze_request;
if(shoot_request != shoot_value) shoot_value = shoot_request;
@@ -147,7 +144,9 @@ void Encoder::start() {
}
-void Encoder::stop() {
+void Encoder::stop(n_savestate save) {
+ // TODO: set save state in package header.
+ // TODO: Flush not yet sent video packages.
record = 0;
if(s) {
if(n) delete n;
diff --git a/src/encoder.h b/src/encoder.h
index 554839c..75788b4 100644
--- a/src/encoder.h
+++ b/src/encoder.h
@@ -37,6 +37,8 @@
#include "util.h"
#include <queue.h>
+#include "package.h"
+
#include "thread.h"
#include <dvframe.h>
@@ -62,7 +64,7 @@ public:
void setCpr(char *newcpr);
void start();
- void stop();
+ void stop(n_savestate save);
void freeze();
void shoot();
diff --git a/src/img_encoder.h b/src/img_encoder.h
index 25779ce..79f4184 100644
--- a/src/img_encoder.h
+++ b/src/img_encoder.h
@@ -23,16 +23,22 @@
#ifndef __RTVIDEOREC_IMGENCODER_H
#define __RTVIDEOREC_IMGENCODER_H
+#include "dvframe.h"
+#include "util.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <avformat.h>
extern "C" {
+#ifdef HAVE_STDLIB_H
+#undef HAVE_STDLIB_H
+#endif
#include <jpeglib.h>
+#ifdef HAVE_STDLIB_H
+#undef HAVE_STDLIB_H
+#endif
}
-#include <dvframe.h>
-
-#include "util.h"
#define VIDEO_BUFFER_SIZE (1024*1024) // FIXME: One size fits all...
@@ -60,5 +66,5 @@ class ImgEncoder {
// AVPacket pkt;
};
-#endif
+#endif /*__RTVIDEOREC_IMGENCODER_H*/
diff --git a/src/mainwindow.cc b/src/mainwindow.cc
index 8bfc53e..85b04cd 100644
--- a/src/mainwindow.cc
+++ b/src/mainwindow.cc
@@ -52,6 +52,9 @@ MainWindow::MainWindow( QWidget* parent, const char* name )
{
error = new Error();
MiavConfig cfg("miav.conf", error);
+ video_width = cfg.readInt("video_width");
+ video_height = cfg.readInt("video_height");
+
int resolution_w = cfg.readInt("pixel_width");
int resolution_h = cfg.readInt("pixel_height");
while(error->hasError()) {
@@ -65,16 +68,6 @@ MainWindow::MainWindow( QWidget* parent, const char* name )
resize(resolution_w, resolution_h);
// Load images
-/*
- QPainter *paint = new QPainter();
- QPicture *pic = new QPicture();
- pic->load(fname, "svg");
- paint->begin(this);
- paint->setWindow(pic->boundingRect());
- paint->drawPicture(0, 0, *pic);
- paint->end();
- */
-
pix_record = new QPixmap();
pix_record->load( PIXMAP_RECORD );
@@ -99,6 +92,10 @@ MainWindow::MainWindow( QWidget* parent, const char* name )
pix_logo = new QPixmap();
pix_logo->load( PIXMAP_LOGO_SMALL );
+ timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), SLOT(redraw_edge()));
+ rec_edge_counter = 0.0f;
+
createGui();
show();
@@ -158,11 +155,11 @@ void MainWindow::createGui()
img_recedge = new QLabel(this);
img_recedge->setBackgroundColor(QColor(160,160,160));
- img_recedge->setFixedSize(740,596);
+ img_recedge->setFixedSize(video_width + 20, video_height + 20);
img_live = new VideoWidget(img_recedge);
// img_live->setErasePixmap( *pix_dummy );
- img_live->setFixedSize(720,576);
+ img_live->setFixedSize(video_width, video_height);
img_live->move(10,10);
g1->addMultiCellWidget ( img_recedge, 0, 0, 0, 2, Qt::AlignHCenter);
@@ -216,6 +213,17 @@ void MainWindow::createGui()
status->message( TXT_READY );
}
+#define GREY 160
+#define SPEED 0.1f
+void MainWindow::redraw_edge()
+{
+ rec_edge_counter += SPEED;
+ float val = abs(sin(rec_edge_counter));
+ img_recedge->setBackgroundColor(QColor((int) ((255 - GREY) * val + GREY),
+ (int) (GREY - (GREY * val)),
+ (int) (GREY - (GREY * val))));
+}
+
QPushButton *MainWindow::createButton(char *caption, int width, int height)
{
QPushButton *btn = new QPushButton(caption, this);
@@ -264,16 +272,47 @@ void MainWindow::checkErrors()
void MainWindow::rec_clicked()
{
- recording = 1 - recording;
- if(recording) {
- img_recedge->setBackgroundColor(red);
+ if(!recording) {
+ recording = 1;
+ // Start flashing the edge
+ rec_edge_counter = 0.0f;
+ timer->start(200);
btn_rec->setPixmap(*pix_stop);
camera->start();
checkErrors();
} else {
- img_recedge->setBackgroundColor(QColor(160,160,160));
- btn_rec->setPixmap(*pix_record);
- camera->stop();
+ switch(MessageBox(this,
+ TXT_ASK_SAVE_TITLE,
+ TXT_ASK_SAVE,
+ TYPE_YES_NO_MAYBE_CANCEL,
+ ICON_QUESTION).exec()) {
+ case MSG_YES:
+ recording = 0;
+ camera->stop(SAVE);
+ timer->stop();
+ img_recedge->setBackgroundColor(QColor(160,160,160));
+ btn_rec->setPixmap(*pix_record);
+ break;
+
+ case MSG_NO:
+ recording = 0;
+ camera->stop(DELETE);
+ timer->stop();
+ img_recedge->setBackgroundColor(QColor(160,160,160));
+ btn_rec->setPixmap(*pix_record);
+ break;
+
+ case MSG_MAYBE:
+ recording = 0;
+ camera->stop(LATER);
+ timer->stop();
+ img_recedge->setBackgroundColor(QColor(160,160,160));
+ btn_rec->setPixmap(*pix_record);
+ break;
+
+ case MSG_CANCEL:
+ break;
+ }
checkErrors();
}
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 25a938b..3b8f73c 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -35,6 +35,7 @@ using namespace std;
#include <qlabel.h>
#include <qpushbutton.h>
#include <qstatusbar.h>
+#include <qtimer.h>
#include "videowidget.h"
#include "camera.h"
@@ -50,6 +51,8 @@ using namespace std;
#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?"
/**
* Images
@@ -80,6 +83,7 @@ public slots:
void rec_clicked();
void shoot_clicked();
void freeze_clicked();
+ void redraw_edge();
private:
Error *error;
@@ -103,6 +107,8 @@ private:
QLabel *lbl_cpr;
QLabel *lbl_name;
+ float rec_edge_counter;
+ QTimer *timer;
QLabel *img_recedge;
QLabel *img_history[NUM_HISTORY];
@@ -119,7 +125,10 @@ private:
bool recording;
bool frozen;
+ // Configuration values
float unit;
+ int video_width;
+ int video_height;
QPushButton *createButton(char *caption, int width, int height);
QLabel *createLabel(char *caption, int width, int height);
diff --git a/src/messagebox.cc b/src/messagebox.cc
index 63bbeee..1975eac 100644
--- a/src/messagebox.cc
+++ b/src/messagebox.cc
@@ -72,9 +72,9 @@ MessageBox::MessageBox(QWidget* parent,
pix_icon->load( PIXMAP_WARNING );
break;
case TYPE_YES_NO:
- pix_icon->load( PIXMAP_QUESTION );
- break;
+ case TYPE_YES_NO_MAYBE:
case TYPE_YES_NO_CANCEL:
+ case TYPE_YES_NO_MAYBE_CANCEL:
pix_icon->load( PIXMAP_QUESTION );
break;
}
@@ -134,6 +134,20 @@ MessageBox::MessageBox(QWidget* parent,
connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));
break;
}
+ case TYPE_YES_NO_MAYBE:
+ {
+ QPushButton *byes = createButton(f, TXT_YES );
+ QPushButton *bno = createButton(f, TXT_NO );
+ QPushButton *bmaybe = createButton(f, TXT_MAYBE );
+ 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 *byes = createButton(f, TXT_YES );
@@ -148,6 +162,23 @@ MessageBox::MessageBox(QWidget* parent,
connect(bno, SIGNAL( clicked() ), SLOT(bno_clicked()));
break;
}
+ case TYPE_YES_NO_MAYBE_CANCEL:
+ {
+ QPushButton *byes = createButton(f, TXT_YES );
+ QPushButton *bcancel = createButton(f, TXT_CANCEL );
+ QPushButton *bno = createButton(f, TXT_NO );
+ QPushButton *bmaybe = createButton(f, TXT_MAYBE );
+ 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;
+ }
}
}
@@ -185,4 +216,10 @@ void MessageBox::bno_clicked()
{
done(MSG_NO);
}
+
+void MessageBox::bmaybe_clicked()
+{
+ done(MSG_MAYBE);
+}
+
#endif/*USE_GUI*/
diff --git a/src/messagebox.h b/src/messagebox.h
index 313d395..72b703f 100644
--- a/src/messagebox.h
+++ b/src/messagebox.h
@@ -50,14 +50,17 @@ typedef enum {
MSG_YES,
MSG_NO,
MSG_CANCEL,
- MSG_OK
+ 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;
@@ -65,9 +68,10 @@ typedef enum {
* Textstrings
*/
#define TXT_OK "Ok"
-#define TXT_CANCEL "Annuler"
+#define TXT_CANCEL "Annulér"
#define TXT_YES "Ja"
#define TXT_NO "Nej"
+#define TXT_MAYBE "Måske"
/**
* Images
@@ -94,6 +98,7 @@ public slots:
void bcancel_clicked();
void byes_clicked();
void bno_clicked();
+ void bmaybe_clicked();
private:
QPixmap *pix_icon;
diff --git a/src/miav.conf b/src/miav.conf
index ba2ceda..c0f5c89 100644
--- a/src/miav.conf
+++ b/src/miav.conf
@@ -3,16 +3,20 @@
#
# Cpr Database configuration
-fisk =
- = true
cpr_host = "cpr.j.auh.dk"
cpr_port = 10301
cpr_timeout = 10000
+# Video source
+#video_width = 720
+#video_height = 576
+video_width = 500
+video_height = 370
+
# Size of the screen in inches
-screensize = 19.0
-pixel_width = 1024
-pixel_height = 768
+screensize = 14.0
+pixel_width = 800
+pixel_height = 600
# How and where to connect to the miav server?
server_addr = "192.168.0.10"
diff --git a/src/package.h b/src/package.h
index db0e5a0..94580ee 100644
--- a/src/package.h
+++ b/src/package.h
@@ -28,6 +28,13 @@
#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;
@@ -40,6 +47,7 @@ typedef struct {
bool record;
bool freeze;
bool snapshot;
+ n_savestate savestate;
} h_data;
struct {
int fisk;
diff --git a/src/server.cc b/src/server.cc
index 22b691f..44abe2d 100644
--- a/src/server.cc
+++ b/src/server.cc
@@ -63,14 +63,20 @@ MovEncoder *newMovEncoder(char* cpr)
char fname[256];
time_t t = time(NULL);
ltime = localtime(&t);
- sprintf(fname, "%.2d%.2d%.2d%.2d%.2d%.2d-%s.mpg", ltime->tm_year + 1900, ltime->tm_mon,
- ltime->tm_mday, ltime->tm_hour, ltime->tm_min, ltime->tm_sec, cpr);
+ sprintf(fname, "%.2d%.2d%.2d%.2d%.2d%.2d-%s.mpg",
+ ltime->tm_year + 1900,
+ ltime->tm_mon,
+ ltime->tm_mday,
+ ltime->tm_hour,
+ ltime->tm_min,
+ ltime->tm_sec, cpr);
enc = new MovEncoder(fname);
return enc;
}
void newConnection(Socket *s)
-{
+{
+ n_savestate savestate = LATER;
n_header h;
DVFrame *f;
DVFrame *freeze_frame = NULL;
@@ -91,6 +97,7 @@ void newConnection(Socket *s)
printf("\tcpr: %s\t", h.header.h_data.cpr);
printf("\tfrz: %d\t", h.header.h_data.freeze);
printf("\tsht: %d\n", h.header.h_data.snapshot);
+ printf("\tsave: %d\n", h.header.h_data.savestate);
if(h.header.h_data.snapshot) {
if(freeze_frame) {
@@ -107,6 +114,10 @@ void newConnection(Socket *s)
enc->encode(f);
}
+ if(h.header.h_data.savestate) {
+ savestate = h.header.h_data.savestate;
+ }
+
if(h.header.h_data.freeze) {
if(freeze_frame) delete freeze_frame;
freeze_frame = f;
@@ -116,14 +127,12 @@ void newConnection(Socket *s)
f = new DVFrame();
}
+
+ // TODO: Use save state
+
delete f;
if(enc) delete enc;
printf("Connection end[pid: %d]...\n", getpid());
}
-/*
-int main(int argc, char *argv[])
-{
-}
-*/
diff --git a/src/util.h b/src/util.h
index b82b782..7921e41 100644
--- a/src/util.h
+++ b/src/util.h
@@ -22,6 +22,9 @@
#ifndef __RTVIDEOREC_UTIL_H
#define __RTVIDEOREC_UTIL_H
+#include <stdio.h>
+//#include <stdlib.h>
+
//#ifdef __cplusplus
//extern "C" {
//#endif