diff options
author | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2005-06-08 02:17:19 +0800 |
---|---|---|
committer | piaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2005-06-08 02:17:19 +0800 |
commit | 9261dc82c1f7d4dcac8f76453804968ee94967e5 (patch) | |
tree | 7b18b06c7a14b58b3acc88f348c3229c54905617 | |
parent | a1cc7925cc0fb26dd4cf48ec0b44b839a56e6710 (diff) | |
download | pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar.gz pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar.bz2 pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar.lz pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar.xz pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.tar.zst pttbbs-9261dc82c1f7d4dcac8f76453804968ee94967e5.zip |
pmore bbs movie: world timeline synchronization model
git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@2791 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r-- | mbbsd/pmore.c | 188 |
1 files changed, 124 insertions, 64 deletions
diff --git a/mbbsd/pmore.c b/mbbsd/pmore.c index 3a2aea8d..d1d9ee9e 100644 --- a/mbbsd/pmore.c +++ b/mbbsd/pmore.c @@ -55,6 +55,7 @@ #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/time.h> #include <ctype.h> #include <string.h> @@ -311,20 +312,29 @@ enum { MFDISP_MOVIE_PLAYING_OLD, } _MFDISP_MOVIE_MODES; -/* typedef struct { - int mode, - compat24; + struct timeval frameclk; + struct timeval synctime; + unsigned char mode, + compat24; } MF_Movie; -MF_Movie mfmov; -*/ +MF_Movie mfmovie; + +#define RESET_MOVIE() { mfmovie.mode = MFDISP_MOVIE_UNKNOWN; mfmovie.compat24 = 1; \ + mfmovie.synctime.tv_sec = mfmovie.synctime.tv_usec = 0; \ + mfmovie.frameclk.tv_sec = mfmovie.frameclk.tv_usec = 0; } MFPROTO unsigned char * mf_movieFrameHeader(unsigned char *p); -int pmore_wait_input(float secs); -int mf_movieNextFrame(float* newsec); -int moviemode = MFDISP_MOVIE_UNKNOWN; -int moviecompat24 = 1; +int pmore_wait_input(struct timeval *ptv); +int mf_movieNextFrame(); +int mf_movieSyncFrame(); + +void float2tv(float f, struct timeval *ptv); + +#define MOVIE_MIN_FRAMECLK (0.1f) +#define MOVIE_SECOND_U (1000000L) + #endif // --------------------------------------------- </Optional Modules> @@ -970,21 +980,21 @@ mf_display() } #ifdef PMORE_USE_ASCII_MOVIE - if(moviemode == MFDISP_MOVIE_PLAYING_OLD && - moviecompat24) + if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD && + mfmovie.compat24) { if(mf.dispedlines == 23) return; } else - if(moviemode == MFDISP_MOVIE_UNKNOWN || - moviemode == MFDISP_MOVIE_PLAYING) + if(mfmovie.mode == MFDISP_MOVIE_UNKNOWN || + mfmovie.mode == MFDISP_MOVIE_PLAYING) { if(mf_movieFrameHeader(mf.dispe)) - switch(moviemode) + switch(mfmovie.mode) { case MFDISP_MOVIE_UNKNOWN: - moviemode = MFDISP_MOVIE_DETECTED; + mfmovie.mode = MFDISP_MOVIE_DETECTED; break; case MFDISP_MOVIE_PLAYING: /* @@ -1453,10 +1463,7 @@ pmore(char *fpath, int promptend) MF_PrettyFormattedHeader bkfh; #ifdef PMORE_USE_ASCII_MOVIE - float frameclk = 1.0f; - - moviecompat24 = 1; - moviemode = MFDISP_MOVIE_UNKNOWN; + RESET_MOVIE(); #endif bkmf = mf; /* simple re-entrant hack */ @@ -1496,14 +1503,14 @@ pmore(char *fpath, int promptend) // clrtoeol(); // this shall be done in mf_display to speed up. #ifdef PMORE_USE_ASCII_MOVIE - switch (moviemode) + switch (mfmovie.mode) { case MFDISP_MOVIE_UNKNOWN: - moviemode = MFDISP_MOVIE_NO; + mfmovie.mode = MFDISP_MOVIE_NO; break; case MFDISP_MOVIE_DETECTED: - moviemode = MFDISP_MOVIE_YES; + mfmovie.mode = MFDISP_MOVIE_YES; { // query if user wants to play movie. @@ -1518,9 +1525,10 @@ pmore(char *fpath, int promptend) w != KEY_UP && w != KEY_LEFT && w != 'q') { - moviemode = MFDISP_MOVIE_PLAYING; + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING; mf_determinemaxdisps(0, 0); // display until last line - mf_movieNextFrame(&frameclk); + mf_movieNextFrame(); MFDISP_DIRTY(); continue; } @@ -1540,31 +1548,31 @@ pmore(char *fpath, int promptend) w -= strlen(s); outs(s); while(w-- > 0) outc(' '); outs(ANSI_RESET); } - if(!pmore_wait_input(frameclk)) + if(mf_movieSyncFrame()) { /* user did not hit anything. * play next frame. */ - if(moviemode == MFDISP_MOVIE_PLAYING) + if(mfmovie.mode == MFDISP_MOVIE_PLAYING) { - if(!mf_movieNextFrame(&frameclk)) + if(!mf_movieNextFrame()) { - moviemode = MFDISP_MOVIE_YES; // nothing more + mfmovie.mode = MFDISP_MOVIE_YES; // nothing more mf_determinemaxdisps(MFNAV_PAGE, 0); mf_forward(0); } } - else if(moviemode == MFDISP_MOVIE_PLAYING_OLD) + else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) { if(mf_viewedAll()) { - moviemode = MFDISP_MOVIE_NO; + mfmovie.mode = MFDISP_MOVIE_NO; mf_determinemaxdisps(MFNAV_PAGE, 0); mf_forward(0); } else { - if(!moviecompat24) + if(!mfmovie.compat24) PMORE_UINAV_FORWARDPAGE(); else mf_forward(22); @@ -1574,10 +1582,10 @@ pmore(char *fpath, int promptend) igetch(); /* TODO simple navigation here? */ - if(moviemode == MFDISP_MOVIE_PLAYING) - moviemode = MFDISP_MOVIE_YES; - else if(moviemode == MFDISP_MOVIE_PLAYING_OLD) - moviemode = MFDISP_MOVIE_NO; + if(mfmovie.mode == MFDISP_MOVIE_PLAYING) + mfmovie.mode = MFDISP_MOVIE_YES; + else if(mfmovie.mode == MFDISP_MOVIE_PLAYING_OLD) + mfmovie.mode = MFDISP_MOVIE_NO; mf_determinemaxdisps(MFNAV_PAGE, 0); mf_forward(0); @@ -2042,18 +2050,23 @@ pmore(char *fpath, int promptend) case 'p': /* play ascii movie again */ - if(moviemode == MFDISP_MOVIE_YES) + if(mfmovie.mode == MFDISP_MOVIE_YES) { - moviemode = MFDISP_MOVIE_PLAYING; + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING; mf_determinemaxdisps(0, 0); // display until last line mf_goTop(); - mf_movieNextFrame(&frameclk); + mf_movieNextFrame(); MFDISP_DIRTY(); } - else if (moviemode == MFDISP_MOVIE_NO) + else if (mfmovie.mode == MFDISP_MOVIE_NO) { static char buf[10]="1"; //move(b_lines-1, 0); + + /* + * TODO scan current page to confirm if this is a new style movie + */ pmore_clrtoeol(b_lines-1, 0); getdata_buf(b_lines - 1, 0, "這可能是傳統動畫檔, " @@ -2062,10 +2075,10 @@ pmore(char *fpath, int promptend) buf, 8, LCECHO); if(buf[0]) { - sscanf(buf, "%f", &frameclk); - if(frameclk < 0.1f) - frameclk = 0.1f; - moviecompat24 = 0; + float nf = 0; + sscanf(buf, "%f", &nf); + float2tv(nf, &mfmovie.frameclk); + mfmovie.compat24 = 0; /* are we really going to start? check termsize! */ if (t_lines != 24) { @@ -2076,11 +2089,12 @@ pmore(char *fpath, int promptend) "要模擬 24 行嗎? (否則會用現在的行數)[Yn] " , ans, 3, LCECHO); if(ans[0] == 'n') - moviecompat24 = 0; + mfmovie.compat24 = 0; else - moviecompat24 = 1; + mfmovie.compat24 = 1; } - moviemode = MFDISP_MOVIE_PLAYING_OLD; + RESET_MOVIE(); + mfmovie.mode = MFDISP_MOVIE_PLAYING_OLD; mf_determinemaxdisps(0, 0); // display until last line MFDISP_DIRTY(); } @@ -2118,10 +2132,9 @@ pmore(char *fpath, int promptend) * override if you have better methods. */ int -pmore_wait_input(float secs) +pmore_wait_input(struct timeval *ptv) { int sel = 0; - struct timeval tv; fd_set readfds; if(num_in_buf() > 0) @@ -2130,26 +2143,20 @@ pmore_wait_input(float secs) FD_ZERO(&readfds); FD_SET(0, &readfds); - tv.tv_sec = (long) secs; - secs -= tv.tv_sec; - tv.tv_usec = (long) (secs * 1000000L); - refresh(); #ifdef STATINC STATINC(STAT_SYSSELECT); #endif - sel = select(1, &readfds, NULL, NULL, &tv); + do { + sel = select(1, &readfds, NULL, NULL, ptv); + } while (sel < 0 && errno == EINTR); + /* EINTR, interrupted. I don't care! */ + if(sel == 0) return 0; - /* when EINTR, what should we do? - * not pretty sure... - */ - /* - if(sel < 0 && errno == EINTR) - return 0; - */ + return 1; } @@ -2167,8 +2174,46 @@ mf_movieFrameHeader(unsigned char *p) return NULL; } +void +float2tv(float f, struct timeval *ptv) +{ + if(f < MOVIE_MIN_FRAMECLK) + f = MOVIE_MIN_FRAMECLK; + ptv->tv_sec = (long) f; + ptv->tv_usec = (f - (long)f) * MOVIE_SECOND_U; +} + +/* + * return meaning: + * I've got synchronized. + * If no (user breaks), return 0 + */ +int mf_movieSyncFrame() +{ + if (mfmovie.synctime.tv_sec > 0) + { + /* synchronize world timeline model */ + struct timeval dv; + gettimeofday(&dv, NULL); + dv.tv_sec = mfmovie.synctime.tv_sec - dv.tv_sec; + if(dv.tv_sec < 0) + return 1; + dv.tv_usec = mfmovie.synctime.tv_usec - dv.tv_usec; + if(dv.tv_usec < 0) { + dv.tv_sec --; + dv.tv_usec += MOVIE_SECOND_U; + } + if(dv.tv_sec < 0) + return 1; + return !pmore_wait_input(&dv); + } else { + /* synchronize each frame clock model */ + return !pmore_wait_input(&mfmovie.frameclk); + } +} + int -mf_movieNextFrame(float *newsec) +mf_movieNextFrame() { do { @@ -2177,6 +2222,13 @@ mf_movieNextFrame(float *newsec) { char buf[16]; int cbuf = 0; + float nf = 0; + + /* process leading */ + if (*p == 'S') { + gettimeofday(&mfmovie.synctime, NULL); + p++; + } while (p < mf.end && ((*p >= '0' && *p <= '9') || *p == '.')) @@ -2184,10 +2236,18 @@ mf_movieNextFrame(float *newsec) buf[cbuf] = 0; if(cbuf) - sscanf(buf, "%f", newsec); + { + sscanf(buf, "%f", &nf); + float2tv(nf, &mfmovie.frameclk); + } - if(*newsec < 0.1f) - *newsec = 0.1f; + if(mfmovie.synctime.tv_sec > 0) + { + mfmovie.synctime.tv_usec += mfmovie.frameclk.tv_usec; + mfmovie.synctime.tv_sec += mfmovie.frameclk.tv_sec; + mfmovie.synctime.tv_sec += mfmovie.synctime.tv_usec / MOVIE_SECOND_U; + mfmovie.synctime.tv_usec %= MOVIE_SECOND_U; + } mf_forward(1); return 1; |