SKFPlayer.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2004-2005  The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "pent_include.h"
00020 #include "SKFPlayer.h"
00021 
00022 #include "u8/ConvertShapeU8.h"
00023 #include "RawArchive.h"
00024 #include "Shape.h"
00025 #include "Texture.h"
00026 #include "SoftRenderSurface.h"
00027 #include "PaletteManager.h"
00028 #include "MusicProcess.h"
00029 #include "AudioProcess.h"
00030 #include "IDataSource.h"
00031 #include "AudioMixer.h"
00032 #include "RawAudioSample.h"
00033 #include "Font.h"
00034 #include "FontManager.h"
00035 #include "RenderedText.h"
00036 
00037 #include "SDL.h"
00038 
00039 
00040 enum SKFAction {
00041         SKF_PlayMusic = 3,
00042         SKF_SlowStopMusic = 4,
00043         SKF_PlaySFX = 5,
00044         SKF_StopSFX = 6,
00045         SKF_SetSpeed = 7,
00046         SKF_FadeOut = 8,
00047         SKF_FadeIn = 9,
00048         SKF_Wait = 12,
00049         SKF_PlaySound = 14,
00050         SKF_FadeWhite = 15,
00051         SKF_ClearSubs = 18
00052 };
00053 
00054 struct SKFEvent {
00055         unsigned int frame;
00056         SKFAction action;
00057         unsigned int data;
00058 };
00059 
00060 // number of steps in a fade
00061 static const int FADESTEPS = 16; // HACK: half speed
00062 
00063 
00064 SKFPlayer::SKFPlayer(RawArchive* movie, int width_, int height_, bool introMusicHack_)
00065         : width(width_), height(height_), skf(movie),
00066           curframe(0), curobject(0), curaction(0), curevent(0), playing(false),
00067           timer(0), framerate(15), fadecolour(0), fadelevel(0), buffer(0), subs(0),
00068           introMusicHack(introMusicHack_)
00069 {
00070         IDataSource* eventlist = skf->get_datasource(0);
00071         if (!eventlist)
00072         {
00073                 perr << "No eventlist found in SKF" << std::endl;
00074                 return;
00075         }
00076 
00077         parseEventList(eventlist);
00078         delete eventlist;
00079 
00080         buffer = RenderSurface::CreateSecondaryRenderSurface(width, height);
00081 }
00082 
00083 SKFPlayer::~SKFPlayer()
00084 {
00085         for (unsigned int i = 0; i < events.size(); ++i)
00086                 delete events[i];
00087 
00088         delete skf;
00089         delete buffer;
00090         delete subs;
00091 }
00092 
00093 void SKFPlayer::parseEventList(IDataSource* eventlist)
00094 {
00095         uint16 frame = eventlist->read2();
00096         while (frame != 0xFFFF) {
00097                 SKFEvent* ev = new SKFEvent;
00098                 ev->frame = frame;
00099                 ev->action = static_cast<SKFAction>(eventlist->read2());
00100                 ev->data = eventlist->read2();
00101                 events.push_back(ev);
00102 
00103                 frame = eventlist->read2();
00104         }
00105 }
00106 
00107 void SKFPlayer::start()
00108 {
00109         buffer->BeginPainting();
00110         buffer->Fill32(0, 0, 0, width, height);
00111         buffer->EndPainting();
00112         MusicProcess* musicproc = MusicProcess::get_instance();
00113         if (musicproc) musicproc->playMusic(0);
00114         playing = true;
00115         lastupdate = SDL_GetTicks();
00116 }
00117 
00118 void SKFPlayer::stop()
00119 {
00120         MusicProcess* musicproc = MusicProcess::get_instance();
00121         if (musicproc && !introMusicHack) musicproc->playMusic(0);
00122         playing = false;
00123 }
00124 
00125 void SKFPlayer::paint(RenderSurface* surf, int /*lerp*/)
00126 {
00127         if (!buffer) return;
00128 
00129         Texture* tex = buffer->GetSurfaceAsTexture();
00130 
00131         if (!fadelevel) {
00132                 surf->Blit(tex, 0, 0, width, height, 0, 0);
00133                 if (subs)
00134                         subs->draw(surf, 60, subtitley);
00135         } else {
00136                 uint32 fade = TEX32_PACK_RGBA(fadecolour,fadecolour,fadecolour,
00137                                                                           (fadelevel*255)/FADESTEPS);
00138                 surf->FadedBlit(tex, 0, 0, width, height, 0, 0, fade);
00139                 if (subs)
00140                         subs->drawBlended(surf, 60, subtitley, fade);
00141         }
00142 }
00143 
00144 void SKFPlayer::run()
00145 {
00146         if (!playing || !buffer) return;
00147 
00148         // if doing something, continue
00149         if (curaction) {
00150                 if (curaction == SKF_FadeOut || curaction == SKF_FadeWhite) {
00151                         fadelevel++;
00152                         if (fadelevel == FADESTEPS) curaction = 0; // done
00153                 } else if (curaction == SKF_FadeIn) {
00154                         fadelevel--;
00155                         if (fadelevel == 0) curaction = 0; // done
00156                 } else {
00157                         pout << "Unknown fade action: " << curaction << std::endl;
00158                 }
00159         }
00160 
00161         // CHECKME: this timing may not be accurate enough...
00162         uint32 now = SDL_GetTicks();
00163         if (lastupdate + (1000/framerate) > now) return;
00164 
00165         lastupdate += (1000/framerate);
00166 
00167         // if waiting, continue to wait
00168         if (timer) {
00169                 timer--;
00170                 return;
00171         }
00172 
00173         Pentagram::Font* redfont;
00174         redfont = FontManager::get_instance()->getGameFont(6, true);
00175 
00176         MusicProcess* musicproc = MusicProcess::get_instance();
00177         AudioProcess* audioproc = AudioProcess::get_instance();
00178 
00179         // handle events for the current frame
00180         while (curevent < events.size() && events[curevent]->frame <= curframe) {
00181 //              pout << "event " << curevent << std::endl;
00182                 switch (events[curevent]->action)
00183                 {
00184                 case SKF_FadeOut:
00185                         curaction = SKF_FadeOut;
00186                         fadecolour = 0;
00187                         fadelevel = 0;
00188 //                      pout << "FadeOut" << std::endl;
00189                         break;
00190                 case SKF_FadeIn:
00191                         curaction = SKF_FadeIn;
00192                         fadelevel = FADESTEPS;
00193 //                      pout << "FadeIn" << std::endl;
00194                         break;
00195                 case SKF_FadeWhite:
00196                         curaction = SKF_FadeWhite;
00197                         fadecolour = 0xFF;
00198                         fadelevel = 0;
00199 //                      pout << "FadeWhite" << std::endl;
00200                         break;
00201                 case SKF_Wait:
00202 //                      pout << "Wait " << events[curevent]->data << std::endl;
00203                         timer = events[curevent]->data;
00204                         curevent++;
00205                         return;
00206                 case SKF_PlayMusic:
00207 //                      pout << "PlayMusic " << events[curevent]->data << std::endl;
00208                         if (musicproc) musicproc->playMusic(events[curevent]->data);
00209                         break;
00210                 case SKF_SlowStopMusic:
00211                         POUT ("SlowStopMusic");
00212                         if (musicproc && !introMusicHack) musicproc->playMusic(0);
00213                         break;
00214                 case SKF_PlaySFX:
00215 //                      pout << "PlaySFX " << events[curevent]->data << std::endl;
00216                         if (audioproc) audioproc->playSFX(events[curevent]->data,0x60,0,0);
00217                         break;
00218                 case SKF_StopSFX:
00219 //                      pout << "StopSFX" << events[curevent]->data << std::endl;
00220                         if (audioproc) audioproc->stopSFX(events[curevent]->data,0);
00221                         break;
00222                 case SKF_SetSpeed:
00223                         POUT("SetSpeed " << events[curevent]->data);
00224 //                      framerate = events[curevent]->data;
00225                         break;
00226                 case SKF_PlaySound:
00227                 {
00228 //                      pout << "PlaySound " << events[curevent]->data << std::endl;
00229 
00230                         if (audioproc) {
00231                                 uint8* buffer = skf->get_object(events[curevent]->data);
00232                                 uint32 bufsize = skf->get_size(events[curevent]->data);
00233                                 Pentagram::AudioSample* s;
00234                                 uint32 rate = buffer[6] + (buffer[7]<<8);
00235                                 bool stereo = (buffer[8] == 2);
00236                                 s = new Pentagram::RawAudioSample(buffer+34, bufsize-34,
00237                                                                                                   rate, true, stereo);
00238                                 audioproc->playSample(s, 0x60, 0);
00239                                 // FIXME: memory leak! (sample is never deleted)
00240                         }
00241 
00242                         // subtitles
00243                         char* textbuf = reinterpret_cast<char*>(
00244                                 skf->get_object(events[curevent]->data-1));
00245                         uint32 textsize = skf->get_size(events[curevent]->data-1);
00246                         if (textsize > 7) {
00247                                 std::string subtitle = (textbuf+6);
00248                                 delete subs;
00249                                 subtitley = textbuf[4] + (textbuf[5]<<8);
00250                                 unsigned int remaining;
00251                                 subs = redfont->renderText(subtitle, remaining, 200, 0,
00252                                                                                    Pentagram::Font::TEXT_CENTER);
00253                         }
00254                         delete textbuf;
00255 
00256 
00257                         break;
00258                 }
00259                 case SKF_ClearSubs:
00260 //                      pout << "ClearSubs" << std::endl;
00261                         delete subs;
00262                         subs = 0;
00263                         break;
00264                 default:
00265                         pout << "Unknown action" << std::endl;
00266                         break;
00267                 }
00268 
00269                 curevent++;
00270         }
00271 
00272         curframe++;
00273 
00274         PaletteManager* palman = PaletteManager::get_instance();
00275         IDataSource* object;
00276 
00277         uint16 objecttype = 0;
00278         do {
00279                 curobject++;
00280                 if (curobject >= skf->getCount()) {
00281                         stop(); // done
00282                         return;
00283                 }
00284 
00285                 // read object
00286                 object = skf->get_datasource(curobject);
00287                 if (!object || object->getSize() < 2)
00288                         continue;
00289 
00290                 objecttype = object->read2();
00291 
00292 //              pout << "Object " << curobject << "/" << skf->getCount()
00293 //                       << ", type = " << objecttype << std::endl;
00294 
00295 
00296                 if (objecttype == 1) {
00297                         palman->load(PaletteManager::Pal_Movie, *object);
00298                 }
00299 
00300                 if (objecttype != 2)
00301                         delete object;
00302 
00303         } while (objecttype != 2);
00304 
00305         if (objecttype == 2) {
00306                 object->seek(0);
00307                 Shape* shape = new Shape(object, &U8SKFShapeFormat);
00308                 Pentagram::Palette* pal= palman->getPalette(PaletteManager::Pal_Movie);
00309                 shape->setPalette(pal);
00310                 buffer->BeginPainting();
00311                 buffer->Paint(shape, 0, 0, 0);
00312                 buffer->EndPainting();
00313                 delete shape;
00314         
00315                 delete object;
00316         }
00317 
00318         timer = 1; // HACK! timing is rather broken currently...
00319 }
00320 

Generated on Fri Jul 27 22:27:37 2007 for pentagram by  doxygen 1.4.7