11
11
#include <unistd.h>
12
12
#include <ctype.h>
13
13
#include <sysexits.h>
14
+ #include <sys/stat.h>
15
+ #include <errno.h>
14
16
15
17
#define BASE_PATH "./gifs/base.gif"
16
18
#define STARTUP_PATH "./gifs/startup.gif"
17
19
#define OTHER_PATH "./gifs/others/"
18
20
#define BLINK_PATH "./gifs/blinks/"
21
+ #define IMMEDIATE_ANIM_PATH "./gifs/PLAYMENOW/"
22
+ #define OVERRIDE_FILE_PATH "./gifs/OVERRIDE/gif.gif"
19
23
#define MAX_FILENAME_LENGTH 256
20
24
#define MAX_PATH_LENGTH 4096
21
25
#define MIN_DELAY_TIME 35 //Smallest delay time that is possible due to hardware limitations (1000ms/30fps=33.3'ms)
@@ -125,6 +129,19 @@ void readFile(const char* _path, int _count, char** _out);
125
129
unsigned int ledMatrixTranslation (int _x , int _y );
126
130
bool numberIsEven (int _number );
127
131
132
+ //delay(): Behaves like usleep(), but polls OVERRIDE_FILE_PATH in the meantime.
133
+ //If that GIF exists, immediately show it.
134
+ void delay (useconds_t usec ) {
135
+ for (useconds_t elapsed = 0 ; elapsed < usec ; elapsed += 10 * 1000 ) {
136
+ usleep (10 * 1000 );
137
+ struct stat buf ;
138
+ //TODO: Properly check that this is indeed a GIF. Or does showExpressionFromFilepath handle that safely?
139
+ while (!stat (OVERRIDE_FILE_PATH , & buf )) {
140
+ showExpressionFromFilepath (OVERRIDE_FILE_PATH , false, false);
141
+ }
142
+ }
143
+ }
144
+
128
145
//Development function toggles
129
146
bool activateLEDModule = true;
130
147
bool realTASBot = true;
@@ -183,6 +200,11 @@ int main(int _argc, char** _argv) {
183
200
//Default palette
184
201
paletteCount = 8 ;
185
202
palette = malloc (sizeof (ws2811_led_t ) * paletteCount );
203
+ if (!palette ) {
204
+ fprintf (stderr , "[ERROR] Failed to allocate palette memory" );
205
+ clearLEDs ();
206
+ exit (EXIT_FAILURE );
207
+ }
186
208
palette [0 ] = 0xFF0000 ; // red
187
209
palette [1 ] = 0xFF8000 ; // orange
188
210
palette [2 ] = 0xFFFF00 ; // yellow
@@ -232,7 +254,7 @@ int main(int _argc, char** _argv) {
232
254
showExpressionFromFilepath (BASE_PATH , false, false);
233
255
}
234
256
235
- usleep (getBlinkDelay () * 1000 );
257
+ delay (getBlinkDelay () * 1000 );
236
258
//blink for a random amount of times
237
259
for (unsigned int blinks = getBlinkAmount (); blinks > 0 ; -- blinks ) {
238
260
showBlinkExpression ();
@@ -242,8 +264,31 @@ int main(int _argc, char** _argv) {
242
264
if (verboseLogging ) {
243
265
printf ("[INFO] Blink #%d for %d milliseconds \n" , blinks , blinkTime );
244
266
}
245
- usleep (blinkTime * 1000 );
267
+ delay (blinkTime * 1000 );
268
+
269
+ //Check for immediate animation to play back.
270
+ DIR * immediate_anim_dir = opendir (IMMEDIATE_ANIM_PATH );
271
+ struct dirent * dir ;
272
+ if (immediate_anim_dir ) { //Null is discarded as this directory is not always expected to exist.
273
+ struct dirent * dir ;
274
+ do {
275
+ dir = readdir (immediate_anim_dir );
276
+ if (dir && strlen (dir -> d_name ) > 4 && !strcmp (dir -> d_name + strlen (dir -> d_name ) - 4 , ".gif" )) {
277
+ char pathinter [PATH_MAX + 1 ];
278
+ sprintf (pathinter , "%s/%s" , IMMEDIATE_ANIM_PATH , dir -> d_name );
279
+ char path [PATH_MAX + 1 ];
280
+ realpath (pathinter , path );
281
+ Animation * animation = readAnimation (path );
282
+ playExpression (animation , false, false);
283
+ remove (path );
284
+ blinks ++ ;
285
+ break ;
286
+ }
287
+ } while (dir );
288
+ closedir (immediate_anim_dir );
289
+ }
246
290
}
291
+
247
292
}
248
293
249
294
//Clean up
@@ -546,7 +591,7 @@ Animation* readAnimation(char* _file) {
546
591
547
592
//Open _file
548
593
int e ;
549
- GifFileType * image = DGifOpenFileName (_file , & e );
594
+ GifFileType * image = DGifOpenFileName (_file , & e );
550
595
if (!image ) {
551
596
fprintf (stderr , "[ERROR] EGifOpenFileName() failed. Couldn't find or open _file: %d\n" , e );
552
597
return false;
@@ -555,7 +600,7 @@ Animation* readAnimation(char* _file) {
555
600
//"Slurp" infos into struct
556
601
if (DGifSlurp (image ) == GIF_ERROR ) {
557
602
fprintf (stderr , "[ERROR] DGifSlurp() failed. Couldn't load infos about GIF: %d\n" , image -> Error );
558
- DGifCloseFile ( image , & e );
603
+ if ( DGifCloseFile ( image , & e ) != GIF_OK ) fprintf ( stderr , "[WARNING] readAnimation: DGifCloseFile returned%d\n" , e );
559
604
return false;
560
605
}
561
606
@@ -572,7 +617,17 @@ Animation* readAnimation(char* _file) {
572
617
573
618
//Process frames
574
619
animation = malloc (sizeof (Animation ));
620
+ if (!animation ) {
621
+ fprintf (stderr , "[ERROR] readAnimation: Failed to allocate Animation" );
622
+ clearLEDs ();
623
+ exit (EXIT_FAILURE );
624
+ }
575
625
AnimationFrame * * animationFrames = malloc (sizeof (AnimationFrame * ) * image -> ImageCount );
626
+ if (!animationFrames ) {
627
+ fprintf (stderr , "[ERROR] readAnimation: Failed to allocate AnimationFrames" );
628
+ clearLEDs ();
629
+ exit (EXIT_FAILURE );
630
+ }
576
631
animation -> frames = animationFrames ;
577
632
animation -> frameCount = image -> ImageCount ;
578
633
animation -> monochrome = true;
@@ -630,6 +685,11 @@ AnimationFrame* readFramePixels(const SavedImage* frame, ColorMapObject* _global
630
685
: _globalMap ; //choose either global or local color map
631
686
632
687
AnimationFrame * animationFrame = malloc (sizeof (AnimationFrame ));
688
+ if (!animationFrame ) {
689
+ fprintf (stderr , "[ERROR] readFramePixels: Failed to allocate animationFrame" );
690
+ clearLEDs ();
691
+ exit (EXIT_FAILURE );
692
+ }
633
693
634
694
bool keepColor = false;
635
695
for (int y = 0 ; y < desc .Height ; ++ y ) {
@@ -697,6 +757,10 @@ ws2811_return_t initLEDs() {
697
757
698
758
//Setup color array
699
759
pixel = malloc (sizeof (ws2811_led_t ) * LED_WIDTH * LED_HEIGHT );
760
+ if (!pixel ) {
761
+ fprintf (stderr , "[ERROR] initLEDs: Failed to allocate color array" );
762
+ exit (EXIT_FAILURE );
763
+ }
700
764
701
765
//Initialize hardware
702
766
ws2811_return_t r ;
@@ -778,7 +842,8 @@ void showRandomExpression(char* _path, bool _useRandomColor, bool _repeatAnimati
778
842
*/
779
843
void showExpressionFromFilepath (char * _filePath , bool _useRandomColor , bool _repeatAnimations ) {
780
844
Animation * animation = readAnimation (_filePath );
781
- playExpression (animation , _useRandomColor , _repeatAnimations );
845
+ if (!animation ) fprintf (stderr , "[WARNING] showExpressionFromFilepath: animation is NULL, skipping\n" );
846
+ else playExpression (animation , _useRandomColor , _repeatAnimations );
782
847
}
783
848
784
849
/**
@@ -913,7 +978,7 @@ void showFrame(AnimationFrame* _frame, ws2811_led_t _color) {
913
978
void freeAnimation (Animation * _animation ) {
914
979
//dirty trick, close file here, after animation. That way DGifCloseFile() can't destroy the animation data
915
980
int e = 0 ;
916
- DGifCloseFile (_animation -> image , & e );
981
+ if ( DGifCloseFile (_animation -> image , & e ) != GIF_OK ) fprintf ( stderr , "[WARNING] freeAnimation: DGifCloseFile returned%d\n" , e );
917
982
if (verboseLogging ) {
918
983
printf ("[INFO] Closed GIF with code %d\n" , e );
919
984
}
@@ -995,6 +1060,11 @@ void readPalette(char* _path) {
995
1060
996
1061
//Read palette into final palette array
997
1062
ws2811_led_t * pal = malloc (sizeof (ws2811_led_t ) * colorCount );
1063
+ if (!pal ) {
1064
+ fprintf (stderr , "[ERROR] readPalette: Failed to allocate palette memory" );
1065
+ clearLEDs ();
1066
+ exit (EXIT_FAILURE );
1067
+ }
998
1068
for (int i = 0 ; i < colorCount ; ++ i ) {
999
1069
int color = strtocol (rawPal [i ]);
1000
1070
if (color != -1 ) {
@@ -1005,6 +1075,7 @@ void readPalette(char* _path) {
1005
1075
} else {
1006
1076
printf ("[WARNING] Skip color %s because of parsing error" , rawPal [i ]);
1007
1077
}
1078
+ free (rawPal [i ]);
1008
1079
}
1009
1080
1010
1081
paletteCount = colorCount ;
@@ -1088,6 +1159,7 @@ bool checkIfDirectoryExist(char* _path) {
1088
1159
closedir (dir );
1089
1160
return true;
1090
1161
}
1162
+ fprintf (stderr , "[WARNING]: directory %s does not exist. Errno is %d\n" , _path , errno );
1091
1163
return false;
1092
1164
}
1093
1165
@@ -1119,7 +1191,12 @@ void readFile(const char* _path, int _count, char** _out) {
1119
1191
//Read line after line into give array
1120
1192
for (int i = 0 ; i < _count ; i ++ ) {
1121
1193
_out [i ] = malloc (sizeof (unsigned int ));
1122
- fscanf (ptr , "%s\n" , _out [i ]);
1194
+ if (!_out [i ]) {
1195
+ fprintf (stderr , "[ERROR] readFile: Failed to allocate memory" );
1196
+ clearLEDs ();
1197
+ exit (EXIT_FAILURE );
1198
+ }
1199
+ if (fscanf (ptr , "%s\n" , _out [i ]) != 1 ) fprintf (stderr , "[ERROR] readFile: Failed to read line %d\n" , i );
1123
1200
}
1124
1201
1125
1202
//Closing the file
@@ -1144,6 +1221,7 @@ int countFilesInDir(char* _path) {
1144
1221
closedir (d );
1145
1222
return counter ;
1146
1223
}
1224
+ fprintf (stderr , "[WARNING]: countFilesInDir() called on nonexistent directory %s. Errno is %d\n" , _path , errno );
1147
1225
return -1 ;
1148
1226
}
1149
1227
@@ -1167,6 +1245,7 @@ bool getFileList(const char* _path, char* _list[]) {
1167
1245
closedir (d );
1168
1246
return true;
1169
1247
}
1248
+ fprintf (stderr , "[WARNING]: getFileList() called on nonexistent directory %s. Errno is %d\n" , _path , errno );
1170
1249
return false;
1171
1250
}
1172
1251
@@ -1223,4 +1302,4 @@ unsigned int ledMatrixTranslation(int _x, int _y) {
1223
1302
bool numberIsEven (int _number ) {
1224
1303
return (_number % 2 == 0 );
1225
1304
}
1226
- //endregion
1305
+ //endregion
0 commit comments