Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DMBasicGUI by
SlideShow.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "SlideShow.h" 00018 #include "Image.h" 00019 #include "mbed_debug.h" 00020 #include "DMBoard.h" 00021 00022 /****************************************************************************** 00023 * Defines and typedefs 00024 *****************************************************************************/ 00025 00026 #define SLIDESHOW_DBG 0 00027 00028 #define NO_SLOT -12 /* Some constant to indicate that no slot is in use */ 00029 00030 /* Helper macros for the Fade transition */ 00031 #define FADE_XRED(__in) (((__in)>>11)&0x1f) 00032 #define FADE_XGREEN(__in) (((__in)>>5)&0x3f) 00033 #define FADE_XBLUE(__in) ((__in)&0x1f) 00034 #define FADE_COMBINE(__old, __new, __mul) \ 00035 ( ((((FADE_XRED(__old)*(8-(__mul)))+(FADE_XRED(__new)*(__mul)))>>3)<<11) \ 00036 | ((((FADE_XGREEN(__old)*(8-(__mul)))+(FADE_XGREEN(__new)*(__mul)))>>3)<<5) \ 00037 | (((FADE_XBLUE(__old)*(8-(__mul)))+(FADE_XBLUE(__new)*(__mul)))>>3) ) 00038 00039 00040 /****************************************************************************** 00041 * Global variables 00042 *****************************************************************************/ 00043 00044 extern volatile uint32_t msTicks; 00045 00046 /****************************************************************************** 00047 * Private Functions 00048 *****************************************************************************/ 00049 00050 void SlideShow::Command::print() 00051 { 00052 switch(type) 00053 { 00054 case Clear: 00055 printf("CMD: Clear screen\n"); 00056 break; 00057 case Goto: 00058 printf("CMD: Goto command %d\n", information); 00059 break; 00060 case LoadImage: 00061 printf("CMD: Load file %s into [%d]\n", fname, information); 00062 break; 00063 case Show: 00064 printf("CMD: Show image [%d] with %s transition\n", information, transition->typeString()); 00065 break; 00066 case Wait: 00067 printf("CMD: Wait %d ms\n", information); 00068 break; 00069 case Callout: 00070 printf("CMD: Callout %d\n", information); 00071 break; 00072 default: 00073 printf("Unknown command\n"); 00074 } 00075 } 00076 00077 SlideShow::SlideShowError SlideShow::Command::handle(SlideShow* ss, int* seqIdx, int* lastTime) 00078 { 00079 SlideShowError result = Ok; 00080 00081 //printf("[%03d] ", *seqIdx); print(); 00082 switch (type) 00083 { 00084 case Clear: 00085 // Use the 3rd back buffer as a fake image for the transition 00086 Image::ImageData_t d; 00087 d.height = ss->screenHeight; 00088 d.width = ss->screenWidth; 00089 d.pixels = &ss->ImageBackBuffer[ss->screenPixels*2]; 00090 d.pointerToFree = NULL; 00091 memset(d.pixels, information, ss->screenBytes); 00092 if (ss->CurrentSlot == NO_SLOT) { 00093 result = transition->execute(ss, NULL, &d); 00094 } else { 00095 result = transition->execute(ss, &(ss->PreparedImages[ss->CurrentSlot]), &d); 00096 } 00097 *lastTime = msTicks; 00098 *seqIdx+=1; 00099 break; 00100 00101 case Goto: 00102 *seqIdx = information; 00103 break; 00104 00105 case LoadImage: 00106 if ((result = ss->loadImage(fname, information)) != Ok) 00107 { 00108 printf("Failed to load image. Aborting...\n"); 00109 break; 00110 } 00111 *seqIdx+=1; 00112 break; 00113 00114 case Show: 00115 if (ss->CurrentSlot == NO_SLOT) { 00116 result = transition->execute(ss, NULL, &(ss->PreparedImages[information])); 00117 } else { 00118 result = transition->execute(ss, &(ss->PreparedImages[ss->CurrentSlot]), &(ss->PreparedImages[information])); 00119 } 00120 if (result != Ok) { 00121 printf("Failed to show image. Aborting...\n"); 00122 break; 00123 } 00124 ss->CurrentSlot = information; 00125 *lastTime = msTicks; 00126 *seqIdx+=1; 00127 break; 00128 00129 case Wait: 00130 ss->delay(*lastTime, information); 00131 *lastTime = msTicks; 00132 *seqIdx+=1; 00133 break; 00134 00135 case Callout: 00136 if (ss->callout != NULL) { 00137 result = ss->callout(ss->calloutId, ss, information); 00138 } else { 00139 // Silently accept that no callout listener is registered 00140 } 00141 *seqIdx+=1; 00142 break; 00143 00144 default: 00145 printf("Found unknown command at index %d\n", *seqIdx); 00146 result = InvalidScript; 00147 } 00148 return result; 00149 } 00150 00151 SlideShow::SlideShowError SlideShow::Transition::execute(SlideShow* ss, Image::ImageData_t* CurrentImage, Image::ImageData_t* NewImage) 00152 { 00153 SlideShowError result = Ok; 00154 00155 do { 00156 00157 // TODO: This would be a good place to handle rendering of differently sized images, 00158 // could unregister+register if NewImage is different from CurrentImage 00159 00160 // Register with the Renderer if needed. 00161 if (ss->rendHnd == 0) { 00162 if (ss->rend == NULL) { 00163 printf("No registered renderer\n"); 00164 result = RuntimeError; 00165 break; 00166 } 00167 00168 // time to register with the renderer 00169 ss->rendHnd = ss->rend->registerUser(ss->layer, ss->drawXoff, ss->drawYoff, 00170 NewImage->width, NewImage->height); 00171 if (ss->rendHnd == 0) { 00172 printf("Failed to register with renderer\n"); 00173 result = RuntimeError; 00174 break; 00175 } 00176 } 00177 00178 switch (t) { 00179 case None: 00180 { 00181 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00182 } 00183 break; 00184 00185 case LeftRight: // TODO: Note that this transition is only implemented for fullscreen mode 00186 { 00187 // Create a buffer with the old image 00188 if (CurrentImage == NULL) { 00189 memset(ss->ImageBackBuffer, 0, ss->screenBytes); 00190 } else { 00191 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00192 } 00193 int end = ss->screenWidth - LeftRight_PixelsToSkip; 00194 for (int x = 0; x < end; x += LeftRight_PixelsToSkip) 00195 { 00196 int off = 0; 00197 for (int y = 0; y < ss->screenHeight; y++) 00198 { 00199 memcpy(ss->ImageBackBuffer + (off+x), NewImage->pixels + (off+x), 00200 LeftRight_PixelsToSkip*sizeof(uint16_t)); 00201 off += ss->screenWidth; 00202 } 00203 00204 // Show the updated image 00205 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00206 00207 // Sleep and do over again 00208 Thread::wait(LeftRight_DelayMs); 00209 } 00210 00211 // Show final image 00212 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00213 } 00214 break; 00215 00216 case DownUp: 00217 { 00218 int imgNumPixels = NewImage->width * NewImage->height; 00219 00220 // Create a buffer with the two images after each other, NewImage below 00221 if (CurrentImage == NULL) { 00222 memset(ss->ImageBackBuffer, 0, imgNumPixels*2); 00223 } else { 00224 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, imgNumPixels*2); 00225 } 00226 memcpy(ss->ImageBackBuffer + imgNumPixels, NewImage->pixels, imgNumPixels*2); 00227 00228 // We will be using a back buffer 00229 for (int i = DownUp_LineSkip/2; i < (NewImage->height - 1); i+=DownUp_LineSkip) 00230 { 00231 // Show image by advancing what is shown one line at a time 00232 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer + i * NewImage->width); 00233 00234 // Sleep and do over again 00235 Thread::wait(DownUp_DelayMs); 00236 } 00237 00238 // show final image 00239 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00240 } 00241 break; 00242 00243 case TopDown: 00244 { 00245 int imgNumPixels = NewImage->width * NewImage->height; 00246 00247 // Create a buffer with the two images after each other, NewImage above 00248 if (CurrentImage == NULL) { 00249 memset(ss->ImageBackBuffer + imgNumPixels, 0, imgNumPixels*2); 00250 } else { 00251 memcpy(ss->ImageBackBuffer + imgNumPixels, CurrentImage->pixels, imgNumPixels*2); 00252 } 00253 memcpy(ss->ImageBackBuffer, NewImage->pixels, imgNumPixels*2); 00254 00255 // We will be using a back buffer 00256 for (int i = NewImage->height - TopDown_LineSkip/2; i > 0; i-=TopDown_LineSkip) 00257 { 00258 // Show image by advancing what is shown one line at a time 00259 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer + i*NewImage->width); 00260 00261 // Sleep and do over again 00262 Thread::wait(TopDown_DelayMs); 00263 } 00264 00265 // show final image 00266 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00267 } 00268 break; 00269 00270 case Blinds: 00271 { 00272 int i; 00273 int blockNumPixels = Blinds_LinesPerBlock * ss->screenWidth; 00274 int blockNumBytes = blockNumPixels * sizeof(uint16_t); 00275 image_t beamBlock = ss->ImageBackBuffer + ss->screenPixels; 00276 image_t bkgBlock = beamBlock + blockNumPixels; 00277 00278 // Create a buffer with the old image 00279 if (CurrentImage == NULL) { 00280 memset(ss->ImageBackBuffer, 0, ss->screenBytes); 00281 } else { 00282 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00283 } 00284 00285 // Create the two coloured blocks 00286 memset(beamBlock, Blinds_BeamColor, blockNumBytes); 00287 memset(bkgBlock, Blinds_BackColor, blockNumBytes); 00288 00289 for (i = 0; i < ss->screenPixels; i += blockNumPixels) 00290 { 00291 // Draw the moving beam, erasing the old image 00292 memcpy(ss->ImageBackBuffer+i, beamBlock, blockNumBytes); 00293 00294 // Fill upp behind the beam with background color 00295 if (i > 0) { 00296 memcpy(ss->ImageBackBuffer+i-blockNumPixels, bkgBlock, blockNumBytes); 00297 } 00298 00299 // Show the updated image 00300 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00301 00302 // Sleep and do over again 00303 Thread::wait(Blinds_DelayMs); 00304 } 00305 memcpy(ss->ImageBackBuffer+i-blockNumPixels, bkgBlock, blockNumBytes); 00306 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00307 Thread::wait(Blinds_DelayMs); 00308 00309 for (i = 0; i < ss->screenPixels; i += blockNumPixels) 00310 { 00311 // Draw the moving beam, erasing the old image 00312 memcpy(ss->ImageBackBuffer+i, beamBlock, blockNumBytes); 00313 00314 // Fill upp behind the beam with the new image 00315 if (i > 0) { 00316 memcpy(ss->ImageBackBuffer+i-blockNumPixels, NewImage->pixels+i-blockNumPixels, blockNumBytes); 00317 } 00318 00319 // Show image by advancing what is shown one line at a time 00320 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00321 00322 // Sleep and do over again 00323 Thread::wait(Blinds_DelayMs); 00324 } 00325 00326 // show final image 00327 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00328 } 00329 break; 00330 00331 case Fade: 00332 { 00333 // Create a buffer with the old image 00334 if (CurrentImage == NULL) { 00335 memset(ss->ImageBackBuffer, 0, ss->screenBytes * 2); // use an extra backbuffer 00336 } else { 00337 memcpy(ss->ImageBackBuffer, CurrentImage->pixels, ss->screenBytes); 00338 } 00339 00340 uint32_t firstY = 0; 00341 uint32_t lastY = NewImage->height; 00342 for (uint32_t y = 0, off=0; y < NewImage->height; y++) { 00343 for (uint32_t x = 0; x < NewImage->width; x++) { 00344 off++; 00345 if (NewImage->pixels[off] != ss->ImageBackBuffer[off]) { 00346 firstY = y; 00347 y = NewImage->height; 00348 break; 00349 } 00350 } 00351 } 00352 for (uint32_t y = NewImage->height-1, off=NewImage->height*NewImage->width-1; y > firstY; y--) { 00353 for (uint32_t x = 0; x < NewImage->width; x++) { 00354 off--; 00355 if (NewImage->pixels[off] != ss->ImageBackBuffer[off]) { 00356 lastY = y; 00357 y = firstY; // to break the outer loop as well 00358 break; 00359 } 00360 } 00361 } 00362 00363 // Gradually fade between the old and new images 00364 for (int pass = 1; pass < 8; pass++) 00365 { 00366 uint16_t* oldImg = CurrentImage==NULL ? &ss->ImageBackBuffer[ss->screenPixels] : &CurrentImage->pixels[firstY*NewImage->width]; 00367 uint16_t* newImg = &NewImage->pixels[firstY*NewImage->width]; 00368 uint16_t* dstImg = &ss->ImageBackBuffer[firstY*NewImage->width]; 00369 for (uint32_t y = firstY; y <= lastY; y++) 00370 { 00371 for (uint32_t x = 0; x < NewImage->width; x++) 00372 { 00373 if (*oldImg != *newImg) { 00374 *dstImg = FADE_COMBINE(*oldImg, *newImg, pass); 00375 } 00376 oldImg++; 00377 newImg++; 00378 dstImg++; 00379 } 00380 } 00381 // Show the updated image 00382 ss->rend->setFramebuffer(ss->rendHnd, ss->ImageBackBuffer); 00383 00384 // Sleep and do over again 00385 Thread::wait(Fade_DelayMs); 00386 } 00387 00388 // show final image 00389 ss->rend->setFramebuffer(ss->rendHnd, NewImage->pixels); 00390 } 00391 break; 00392 00393 case Unknown: 00394 default: 00395 result = RuntimeError; 00396 } 00397 } while(0); 00398 00399 return result; 00400 } 00401 00402 SlideShow::SlideShowError SlideShow::loadFile(const char* path, uint8_t** pData, uint32_t* pSize) 00403 { 00404 FILE* f = NULL; 00405 uint32_t pos, size, num; 00406 SlideShowError result = Ok; 00407 00408 *pData = NULL; 00409 *pSize = 0; 00410 00411 if (fileMutex != NULL) { 00412 fileMutex->lock(); 00413 } 00414 do 00415 { 00416 f = fopen(path, "r"); 00417 if (f == NULL) { 00418 printf("Failed to open file %s for reading\n", path); 00419 result = FileError; 00420 break; 00421 } 00422 00423 // Determine file size 00424 pos = ftell(f); 00425 fseek(f, 0, SEEK_END); 00426 size = ftell(f); 00427 fseek(f, pos, SEEK_SET); 00428 00429 // Allocate memory to read into 00430 *pData = (unsigned char*)malloc(size); 00431 if (*pData == NULL) { 00432 printf("Failed to allocate %lu bytes to load %s into\n", size, path); 00433 result = OutOfMemory; 00434 break; 00435 } 00436 00437 // Read entire file 00438 *pSize = size; 00439 pos = 0; 00440 do { 00441 num = fread(*pData + pos, 1, size, f); 00442 if (num > 0) { 00443 size -= num; 00444 pos += num; 00445 } 00446 } while ((num > 0) && (size > 0)); 00447 00448 if (size != 0) { 00449 printf("Failed to read entire %s, got %lu of %lu\n", path, pos, *pSize); 00450 result = FileError; 00451 break; 00452 } 00453 00454 // All OK 00455 00456 } while(0); 00457 00458 if (f != NULL) { 00459 fclose(f); 00460 } 00461 if (result != Ok) { 00462 if (*pData != NULL) { 00463 free(*pData); 00464 *pData = NULL; 00465 *pSize = 0; 00466 } 00467 } 00468 00469 if (fileMutex != NULL) { 00470 fileMutex->unlock(); 00471 } 00472 00473 return result; 00474 } 00475 00476 00477 // pBuf in, pOffset in/out, pLine out 00478 // returns 0 as long as a token is found 00479 int SlideShow::getNextLine(char* pBuf, int* pOffset, char** ppLine) 00480 { 00481 int pos = *pOffset; 00482 int result = -1; 00483 00484 // trim whitespace from start of line 00485 while ((pBuf[pos] == ' ') || (pBuf[pos] == '\t')) 00486 { 00487 pos++; 00488 } 00489 *ppLine = &(pBuf[pos]); 00490 00491 while (pBuf[pos] != '\0') 00492 { 00493 if ((pBuf[pos] == '\r') || (pBuf[pos] == '\n')) 00494 { 00495 // found the next end of line 00496 pBuf[pos++] = '\0'; 00497 result = 0; 00498 00499 // move past all end-of-line characters 00500 while ((pBuf[pos] == '\r') || (pBuf[pos] == '\n')) 00501 { 00502 pos++; 00503 } 00504 break; 00505 } 00506 pos++; 00507 } 00508 00509 *pOffset = pos; 00510 return result; 00511 } 00512 00513 // pLine in, ppPart1 out, ppPart2 out, ppPart3 out 00514 // returns number of found parts 00515 int SlideShow::splitLine(char* pLine, char** ppPart1, char** ppPart2, char** ppPart3) 00516 { 00517 int pos = 0; 00518 int found = 0; 00519 00520 *ppPart1 = NULL; 00521 *ppPart2 = NULL; 00522 *ppPart3 = NULL; 00523 00524 if (*pLine != '\0') 00525 { 00526 *ppPart1 = &(pLine[0]); 00527 found++; 00528 00529 while (pLine[pos] != '\0') 00530 { 00531 if (pLine[pos] == ' ') 00532 { 00533 // found the next token separator 00534 pLine[pos++] = '\0'; 00535 found++; 00536 00537 // move past all token separator characters 00538 while (pLine[pos] == ' ') 00539 { 00540 pos++; 00541 } 00542 00543 // start looking for end of next token 00544 if (found == 2) 00545 { 00546 *ppPart2 = &(pLine[pos]); 00547 } 00548 else if (found == 3) 00549 { 00550 *ppPart3 = &(pLine[pos]); 00551 } 00552 } 00553 pos++; 00554 } 00555 } 00556 00557 return found; 00558 } 00559 00560 // returns index of pLabel or -1 if it doesn't exist 00561 int SlideShow::findLabel(LabelInfo* pLabels, int numLabels, const char* pLabel) 00562 { 00563 int i; 00564 for (i = 0; i < numLabels; i++) 00565 { 00566 if (strcmp(pLabels[i].pLabel, pLabel) == 0) 00567 { 00568 return pLabels[i].index; 00569 } 00570 } 00571 return -1; 00572 } 00573 00574 void SlideShow::freeSequence(void) 00575 { 00576 if (allocatedSequenceItems > 0) { 00577 for (int i = 0; i < usedSequenceItems; i++) { 00578 delete Sequence[i]; 00579 } 00580 free(Sequence); 00581 Sequence = NULL; 00582 allocatedSequenceItems = 0; 00583 usedSequenceItems = 0; 00584 } 00585 } 00586 00587 SlideShow::SlideShowError SlideShow::expandSequence() 00588 { 00589 int newSize = allocatedSequenceItems + 20; 00590 Command** newPtr = (Command**)realloc(Sequence, newSize * sizeof(Command*)); 00591 if (newPtr != NULL) { 00592 Sequence = newPtr; 00593 allocatedSequenceItems = newSize; 00594 return Ok; 00595 } else { 00596 return OutOfMemory; 00597 } 00598 } 00599 00600 SlideShow::SlideShowError SlideShow::parseScript(char* pBuf) 00601 { 00602 char* pLine = NULL; 00603 int offset = 0; 00604 LabelInfo Labels[10] = {0}; 00605 int numLabels = 0; 00606 LabelInfo UnresolvedGotos[10] = {0}; 00607 int numUnresolvedGotos = 0; 00608 int i; 00609 SlideShowError result; 00610 00611 // cleanup old sequences 00612 freeSequence(); 00613 00614 // prepare the new one 00615 result = expandSequence(); 00616 if (result != Ok) { 00617 return result; 00618 } 00619 00620 // start parsing the new sequence 00621 while (getNextLine(pBuf, &offset, &pLine) == 0) 00622 { 00623 if (*pLine == '#') 00624 { 00625 // found a comment line 00626 } 00627 else 00628 { 00629 char* pCommand; 00630 char* pArg1; 00631 char* pArg2; 00632 int num = splitLine(pLine, &pCommand, &pArg1, &pArg2); 00633 00634 if ((num >= 1) && (num <= 3) && (strcmp(pCommand, "clear") == 0)) 00635 { 00636 if (num == 1) { 00637 Sequence[usedSequenceItems] = new Command(Command::Clear, 0xff, new Transition("none")); 00638 } else if (num == 2) { 00639 Sequence[usedSequenceItems] = new Command(Command::Clear, strtol(pArg1, NULL, 16), new Transition("none")); 00640 } else { 00641 Transition* t = new Transition(pArg2); 00642 if (t->type() == Transition::Unknown) { 00643 printf("Found invalid transition '%s'. Aborting...\n", pArg2); 00644 result = InvalidScript; 00645 break; 00646 } 00647 Sequence[usedSequenceItems] = new Command(Command::Clear, strtol(pArg1, NULL, 16), t); 00648 } 00649 } 00650 else if ((num == 3) && (strcmp(pCommand, "show") == 0)) 00651 { 00652 Transition* t = new Transition(pArg2); 00653 if (t->type() == Transition::Unknown) { 00654 printf("Found invalid transition '%s'. Aborting...\n", pArg2); 00655 result = InvalidScript; 00656 break; 00657 } 00658 Sequence[usedSequenceItems] = new Command(Command::Show, atoi(pArg1), t); 00659 } 00660 else if ((num == 2) && (strcmp(pCommand, "wait") == 0)) 00661 { 00662 Sequence[usedSequenceItems] = new Command(Command::Wait, atoi(pArg1)); 00663 } 00664 else if ((num == 2) && (strcmp(pCommand, "callout") == 0)) 00665 { 00666 Sequence[usedSequenceItems] = new Command(Command::Callout, atoi(pArg1)); 00667 } 00668 else if ((num == 2) && (strcmp(pCommand, "label") == 0)) 00669 { 00670 int index = findLabel(&(Labels[0]), numLabels, pArg1); 00671 if (index == -1) 00672 { 00673 // found a new label 00674 Labels[numLabels].index = usedSequenceItems; 00675 Labels[numLabels].pLabel = pArg1; 00676 numLabels++; 00677 00678 // A label doesn't occupy a slot in the sequence 00679 usedSequenceItems--; 00680 } 00681 else 00682 { 00683 // label already declared 00684 printf("Found a second declaration of label '%s'. Aborting...\n", pArg1); 00685 result = InvalidScript; 00686 break; 00687 } 00688 } 00689 else if ((num == 2) && (strcmp(pCommand, "goto") == 0)) 00690 { 00691 int index = findLabel(&(Labels[0]), numLabels, pArg1); 00692 if (index == -1) 00693 { 00694 // couldn't find the label we are looking for so we 00695 // wait for now 00696 UnresolvedGotos[numUnresolvedGotos].index = usedSequenceItems; 00697 UnresolvedGotos[numUnresolvedGotos].pLabel = pArg1; 00698 numUnresolvedGotos++; 00699 } 00700 00701 // Create the command 00702 Sequence[usedSequenceItems] = new Command(Command::Goto, index); 00703 } 00704 else if ((num == 3) && (strcmp(pCommand, "load") == 0)) 00705 { 00706 Sequence[usedSequenceItems] = new Command(Command::LoadImage, atoi(pArg2), NULL, pArg1, pathPrefix); 00707 if (Sequence[usedSequenceItems]->info() >= MaxNumPreparedImages) { 00708 printf("Attempting to load into invalid slot %d, have 0..%d. Aborting...\n", Sequence[usedSequenceItems]->info(), MaxNumPreparedImages); 00709 result = InvalidScript; 00710 break; 00711 } 00712 } 00713 else 00714 { 00715 // unknown command 00716 printf("Found unknown command '%s'. Aborting...\n", pCommand); 00717 result = InvalidScript; 00718 break; 00719 } 00720 00721 // start looking for next part in the sequence 00722 usedSequenceItems++; 00723 00724 // assure we don't pass memory limit 00725 if (usedSequenceItems >= allocatedSequenceItems) 00726 { 00727 result = expandSequence(); 00728 if (result != Ok) { 00729 printf("Failed to allocate memory to hold sequence. Aborting...\n"); 00730 break; 00731 } 00732 } 00733 } 00734 } 00735 00736 // Resolve any unresolved gotos. Happens when the label is on 00737 // a line with a higher line number than the goto statement. 00738 for (i = 0; i < numUnresolvedGotos && result==Ok; i++) 00739 { 00740 int index = findLabel(&(Labels[0]), numLabels, UnresolvedGotos[i].pLabel); 00741 if (index == -1) 00742 { 00743 printf("Unable to find label '%s' used in goto statement. Aborting...\n", UnresolvedGotos[i].pLabel); 00744 result = InvalidScript; 00745 } 00746 else 00747 { 00748 // Update the goto element with the correct index of the label 00749 Sequence[UnresolvedGotos[i].index]->updateInfo(index); 00750 } 00751 } 00752 00753 if (result==Ok && usedSequenceItems == 0) 00754 { 00755 printf("Found no sequence. Aborting...\n"); 00756 result = InvalidScript; 00757 } 00758 return result; 00759 } 00760 00761 SlideShow::SlideShowError SlideShow::loadImage(const char* pFileName, int slot) 00762 { 00763 SlideShowError result = Ok; 00764 00765 if (PreparedImages[slot].pointerToFree != NULL) { 00766 free(PreparedImages[slot].pointerToFree); 00767 PreparedImages[slot].pointerToFree = NULL; 00768 } 00769 00770 if (Image::decode(pFileName, Image::RES_16BIT, &(PreparedImages[slot]), fileMutex) != 0) { 00771 printf("Failed to decode file %s as image\n", pFileName); 00772 result = FileError; 00773 } 00774 00775 return result; 00776 } 00777 void SlideShow::delay(int lastTime, int millis) 00778 { 00779 int timeToWait = (lastTime + millis) - msTicks; 00780 if (timeToWait > 0) { 00781 Thread::wait(timeToWait); 00782 } 00783 } 00784 00785 SlideShow::SlideShowError SlideShow::runScript() 00786 { 00787 SlideShowError result = Ok; 00788 int seqIndex = 0; 00789 int lastTime = 0; 00790 00791 while ((result == Ok) && (seqIndex < this->usedSequenceItems)) 00792 { 00793 result = Sequence[seqIndex]->handle(this, &seqIndex, &lastTime); 00794 00795 if (abortBeforeNextStep) { 00796 break; 00797 } 00798 } 00799 00800 // if (*pAbort) 00801 // { 00802 // return SLIDE_USER_ABORT; 00803 // } 00804 // else 00805 // { 00806 // return SLIDE_SCRIPT_END; 00807 // } 00808 return Ok; 00809 } 00810 00811 00812 /****************************************************************************** 00813 * Public Functions 00814 *****************************************************************************/ 00815 00816 SlideShow::SlideShow(Renderer* r, const char* pathPrefix, int xoff, int yoff, int layer, Mutex* fileMutex) 00817 { 00818 Display* disp = DMBoard::instance().display(); 00819 this->screenWidth = disp->width(); 00820 this->screenHeight = disp->height(); 00821 this->screenPixels = this->screenWidth * this->screenHeight; 00822 this->drawXoff = xoff; 00823 this->drawYoff = yoff; 00824 00825 // Assume screen->bpp == Bpp_16 00826 this->screenBytes = 2 * this->screenPixels; 00827 00828 this->ImageBackBuffer = NULL; 00829 this->Sequence = NULL; 00830 this->allocatedSequenceItems = 0; 00831 this->usedSequenceItems = 0; 00832 00833 this->pathPrefix = pathPrefix; 00834 00835 this->CurrentSlot = NO_SLOT; 00836 00837 memset(PreparedImages, 0, MaxNumPreparedImages * sizeof(Image::ImageData_t)); 00838 00839 this->fileMutex = fileMutex; 00840 00841 this->rend = r; 00842 this->rendHnd = 0; 00843 this->layer = layer; 00844 00845 this->callout = NULL; 00846 00847 this->abortBeforeNextStep = false; 00848 } 00849 00850 SlideShow::~SlideShow() 00851 { 00852 if (ImageBackBuffer != NULL) { 00853 free(ImageBackBuffer); 00854 ImageBackBuffer = NULL; 00855 } 00856 for (int i = 0; i < MaxNumPreparedImages; i++) { 00857 if (PreparedImages[i].pointerToFree != NULL) { 00858 free(PreparedImages[i].pointerToFree); 00859 } 00860 } 00861 00862 freeSequence(); 00863 00864 if ((rendHnd != 0) && (rend != NULL)) { 00865 rend->unregisterUser(rendHnd); 00866 } 00867 00868 //memset(PreparedImages, 0, MaxNumPreparedImages * sizeof(Image::ImageData_t)); 00869 } 00870 00871 SlideShow::SlideShowError SlideShow::prepare(const char* scriptFile) 00872 { 00873 uint8_t* pBuf = NULL; 00874 uint32_t size = 0; 00875 SlideShowError result = InvalidScript; 00876 00877 do 00878 { 00879 if (ImageBackBuffer == NULL) { 00880 // Back buffer will be able to hold three images 00881 ImageBackBuffer = (image_t)malloc(screenBytes * 3); 00882 if (ImageBackBuffer == NULL) { 00883 result = OutOfMemory; 00884 break; 00885 } 00886 } 00887 00888 // Read the contents of the file into a newly allocated buffer 00889 result = loadFile(scriptFile, &pBuf, &size); 00890 if (result != Ok) 00891 { 00892 break; 00893 } 00894 00895 //printf("Parsing buffer...\n"); 00896 00897 // Parse buffer to create the script sequence 00898 result = parseScript((char*)pBuf); 00899 00900 } while (0); 00901 00902 // Release resources 00903 if (pBuf != NULL) 00904 { 00905 free(pBuf); 00906 pBuf = NULL; 00907 } 00908 if (result != Ok) { 00909 freeSequence(); 00910 } 00911 00912 return result; 00913 } 00914 00915 SlideShow::SlideShowError SlideShow::run() 00916 { 00917 //printf("Executing script...\n"); 00918 this->abortBeforeNextStep = false; 00919 return runScript(); 00920 } 00921 00922 void SlideShow::setCalloutHandler(calloutFunc func, int calloutId) 00923 { 00924 this->callout = func; 00925 this->calloutId = calloutId; 00926 } 00927 00928 void SlideShow::releaseScreen(void) 00929 { 00930 if ((rendHnd != 0) && (rend != NULL)) { 00931 rend->unregisterUser(rendHnd); 00932 } 00933 rendHnd = 0; 00934 }
Generated on Wed Jul 13 2022 03:01:51 by
1.7.2
