Add a screen rotation class (time multiplexing).
authorSteinar H. Gunderson <sesse@samfundet.no>
Sun, 20 Feb 2005 01:26:14 +0000 (01:26 +0000)
committerSteinar H. Gunderson <sesse@samfundet.no>
Sun, 20 Feb 2005 01:26:14 +0000 (01:26 +0000)
bigscreen/Makefile
bigscreen/ccbs_bigscreen.cpp
bigscreen/rotatescreen.cpp [new file with mode: 0644]
bigscreen/rotatescreen.h [new file with mode: 0644]

index 2afcd30..42b031f 100644 (file)
@@ -4,7 +4,7 @@ CPPFLAGS=-I/usr/include/postgresql $(shell freetype-config --cflags) -Itinyptc/
 CXXFLAGS=-g -Wall
 LDFLAGS=-L/usr/X11R6/lib
 LIBS=$(shell freetype-config --libs) $(shell libpq3-config) -lpqxx tinyptc/libtinyptc.a -lX11
-CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o flagtrigger.o widestring.o fetch_current_tournament.o fetch_list_of_active_groups.o fetch_max_score_for_song.o fetch_max_score_for_player.o fetch_group.o fonts.o groupscreen.o splitscreen.o screen.o
+CCBS_BIGSCREEN_OBJS=ccbs_bigscreen.o flagtrigger.o widestring.o fetch_current_tournament.o fetch_list_of_active_groups.o fetch_max_score_for_song.o fetch_max_score_for_player.o fetch_group.o fonts.o groupscreen.o splitscreen.o rotatescreen.o screen.o
 
 all: ccbs-bigscreen
 
index 2114093..829f84d 100644 (file)
 #include "fonts.h"
 #include "groupscreen.h"
 #include "splitscreen.h"
+#include "rotatescreen.h"
 
 Tournament active_tournament;
 std::vector<SkeletonGroup> active_groups;
 std::vector<GenericScreen *> screens;
-SplitScreen *mainscreen = NULL;
+//SplitScreen *mainscreen = NULL;
+RotateScreen *mainscreen = NULL;
 unsigned char framebuf[800 * 600 * 4], screenbuf[800 * 600 * 4];
 
 void init(pqxx::connection &conn)
@@ -31,6 +33,8 @@ void init(pqxx::connection &conn)
        conn.perform(FetchCurrentTournament(&active_tournament));
        conn.perform(FetchListOfActiveGroups(&active_groups));
 
+       mainscreen = new RotateScreen();
+       
        if (active_tournament.id == -1) {
                std::fprintf(stderr, "No active tournament\n");
        } else {
@@ -41,6 +45,7 @@ void init(pqxx::connection &conn)
                                i->tournament, i->round, i->parallel);
 
                        screens.push_back(new GroupScreen(conn, i->tournament, i->round, i->parallel));
+                       mainscreen->add_screen(screens[screens.size() - 1]);
                }
        }
 
@@ -50,7 +55,7 @@ void init(pqxx::connection &conn)
        screens.push_back(NULL);
        screens.push_back(NULL);
 
-       mainscreen = new SplitScreen(screens[0], screens[1], screens[2], screens[3]);
+       //mainscreen = new SplitScreen(screens[0], screens[1], screens[2], screens[3]);
 }
 
 void main_loop(pqxx::connection &conn)
diff --git a/bigscreen/rotatescreen.cpp b/bigscreen/rotatescreen.cpp
new file mode 100644 (file)
index 0000000..0997e5c
--- /dev/null
@@ -0,0 +1,78 @@
+#include <cstring>
+#include "rotatescreen.h"
+
+RotateScreen::RotateScreen()
+       : valid(false), current_screen(0)
+{
+}
+
+RotateScreen::~RotateScreen()
+{
+}
+
+bool RotateScreen::check_invalidated()
+{
+       if (!valid)
+               return true;
+
+       if (needs_update())
+               return true;
+       
+       for (unsigned i = 0; i < subscreens.size(); ++i) {
+               if (subscreens[i].screen->check_invalidated())
+                       return true;
+       }
+
+       return false;
+}
+
+void RotateScreen::draw(unsigned char *buf)
+{
+       bool force = false;
+       
+       // push any invalidated screen first (for now)
+       for (unsigned i = 0; i < subscreens.size(); ++i) {
+               if (subscreens[i].screen->check_invalidated()) {
+                       current_screen = i;
+                       force = true;
+               }
+       }
+
+       // check if we want to go to the next screen
+       if (valid && !force && needs_update()) {
+               current_screen = (current_screen + 1) % subscreens.size();
+               gettimeofday(&last_update, NULL);
+       }
+
+       if (subscreens[current_screen].screen->check_invalidated())
+               subscreens[current_screen].screen->draw(subscreens[current_screen].buf);
+       
+       memcpy(buf, subscreens[current_screen].buf, 800 * 600 * 4);
+
+       if (!valid) {
+               valid = true;
+               gettimeofday(&last_update, NULL);
+       }
+}
+       
+// note: makes no sense if valid=false!
+bool RotateScreen::needs_update()
+{
+       struct timeval now;
+       gettimeofday(&now, NULL);
+
+       double since = double(now.tv_sec - last_update.tv_sec) +
+               double(now.tv_usec - last_update.tv_usec) * 1.0e-6;
+
+       return (since >= 10.0);
+}
+
+void RotateScreen::add_screen(GenericScreen *screen)
+{
+       Subscreen ss;
+       ss.buf = new unsigned char[800 * 600 * 4];
+       ss.screen = screen;
+
+       subscreens.push_back(ss);
+}
+
diff --git a/bigscreen/rotatescreen.h b/bigscreen/rotatescreen.h
new file mode 100644 (file)
index 0000000..0883ca2
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _ROTATESCREEN_H
+#define _ROTATESCREEN_H 1
+
+#include <vector>
+#include <time.h>
+#include <sys/time.h>
+#include "screen.h"
+
+/* 
+ * Doesn't rotate the screens, but rotate _between_ them (ie. show
+ * one at a time). :-)
+ */
+struct Subscreen {
+       unsigned char *buf;
+       GenericScreen *screen;
+};
+
+class RotateScreen : public GenericScreen {
+private:
+       bool valid;
+       std::vector<Subscreen> subscreens;
+       unsigned current_screen;
+
+       struct timeval last_update;
+
+       bool needs_update();
+       
+public:
+       RotateScreen();
+       virtual ~RotateScreen();
+
+       bool check_invalidated();
+       void draw(unsigned char *buf);
+
+       void add_screen(GenericScreen *screen);
+//     void remove_screen(GenericScreen *screen);
+};
+
+#endif /* !defined(_ROTATESCREEN_H) */