summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/mpegplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/mpegplayer.c')
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c87
1 files changed, 72 insertions, 15 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 48bb73065c..b228a88dda 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -217,23 +217,26 @@ enum wvs_status_enum
217 217
218enum wvs_bits 218enum wvs_bits
219{ 219{
220 WVS_REFRESH_DEFAULT = 0x0000, 220 WVS_REFRESH_DEFAULT = 0x0000, /* Only refresh elements when due */
221 WVS_REFRESH_VOLUME = 0x0001, 221 /* Refresh the... */
222 WVS_REFRESH_TIME = 0x0002, 222 WVS_REFRESH_VOLUME = 0x0001, /* ...volume display */
223 WVS_REFRESH_STATUS = 0x0004, 223 WVS_REFRESH_TIME = 0x0002, /* ...time display+progress */
224 WVS_REFRESH_BACKGROUND = 0x0008, 224 WVS_REFRESH_STATUS = 0x0004, /* ...playback status icon */
225 WVS_REFRESH_VIDEO = 0x0010, 225 WVS_REFRESH_BACKGROUND = 0x0008, /* ...background (implies ALL) */
226 WVS_REFRESH_RESUME = 0x0020, 226 WVS_REFRESH_VIDEO = 0x0010, /* ...video image upon timeout */
227 WVS_NODRAW = 0x8000, 227 WVS_REFRESH_RESUME = 0x0020, /* Resume playback upon timeout */
228 WVS_SHOW = 0x4000, 228 WVS_NODRAW = 0x8000, /* OR bitflag - don't draw anything */
229 WVS_HIDE = 0x0000, 229 WVS_SHOW = 0x4000, /* OR bitflag - show the WVS */
230 WVS_REFRESH_ALL = 0x001f, 230 WVS_HIDE = 0x0000, /* hide the WVS (aid readability) */
231 WVS_REFRESH_ALL = 0x000f, /* Only immediate graphical elements */
231}; 232};
232 233
234/* Status icons selected according to font height */
233extern const unsigned char mpegplayer_status_icons_8x8x1[]; 235extern const unsigned char mpegplayer_status_icons_8x8x1[];
234extern const unsigned char mpegplayer_status_icons_12x12x1[]; 236extern const unsigned char mpegplayer_status_icons_12x12x1[];
235extern const unsigned char mpegplayer_status_icons_16x16x1[]; 237extern const unsigned char mpegplayer_status_icons_16x16x1[];
236 238
239/* Main border areas that contain WVS elements */
237#define WVS_BDR_L 2 240#define WVS_BDR_L 2
238#define WVS_BDR_T 2 241#define WVS_BDR_T 2
239#define WVS_BDR_R 2 242#define WVS_BDR_R 2
@@ -287,6 +290,7 @@ static void wvs_show(unsigned show);
287#endif 290#endif
288 291
289#ifdef HAVE_LCD_COLOR 292#ifdef HAVE_LCD_COLOR
293/* Blend two colors in 0-100% (0-255) mix of c2 into c1 */
290static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount) 294static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount)
291{ 295{
292 int r1 = RGB_UNPACK_RED(c1); 296 int r1 = RGB_UNPACK_RED(c1);
@@ -303,6 +307,9 @@ static unsigned draw_blendcolor(unsigned c1, unsigned c2, unsigned char amount)
303} 307}
304#endif 308#endif
305 309
310/* Drawing functions that operate rotated on LCD_PORTRAIT displays -
311 * most are just wrappers of lcd_* functions with transforms applied.
312 * The origin is the upper-left corner of the WVS area */
306#ifdef HAVE_LCD_COLOR 313#ifdef HAVE_LCD_COLOR
307static void draw_update_rect(int x, int y, int width, int height) 314static void draw_update_rect(int x, int y, int width, int height)
308{ 315{
@@ -368,7 +375,8 @@ static void draw_hline(int x1, int x2, int y)
368#ifdef LCD_PORTRAIT 375#ifdef LCD_PORTRAIT
369/* Portrait displays need rotated text rendering */ 376/* Portrait displays need rotated text rendering */
370 377
371/* Limited function that only renders in DRMODE_FG */ 378/* Limited function that only renders in DRMODE_FG and uses absolute screen
379 * coordinates */
372static void draw_oriented_mono_bitmap_part(const unsigned char *src, 380static void draw_oriented_mono_bitmap_part(const unsigned char *src,
373 int src_x, int src_y, 381 int src_x, int src_y,
374 int stride, int x, int y, 382 int stride, int x, int y,
@@ -609,6 +617,7 @@ static void wvs_cancel_refresh(unsigned refresh)
609 wvs.auto_refresh &= ~refresh; 617 wvs.auto_refresh &= ~refresh;
610} 618}
611 619
620/* Refresh the background area */
612static void wvs_refresh_background(void) 621static void wvs_refresh_background(void)
613{ 622{
614 char buf[32]; 623 char buf[32];
@@ -618,6 +627,7 @@ static void wvs_refresh_background(void)
618 rb->lcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID); 627 rb->lcd_set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
619 628
620#ifdef HAVE_LCD_COLOR 629#ifdef HAVE_LCD_COLOR
630 /* Draw a "raised" area for our graphics */
621 rb->lcd_set_background(draw_blendcolor(bg, LCD_WHITE, 192)); 631 rb->lcd_set_background(draw_blendcolor(bg, LCD_WHITE, 192));
622 draw_hline(0, wvs.width, 0); 632 draw_hline(0, wvs.width, 0);
623 633
@@ -635,6 +645,7 @@ static void wvs_refresh_background(void)
635 645
636 vo_rect_set_ext(&wvs.update_rect, 0, 0, wvs.width, wvs.height); 646 vo_rect_set_ext(&wvs.update_rect, 0, 0, wvs.width, wvs.height);
637#else 647#else
648 /* Give contrast with the main background */
638 rb->lcd_set_background(LCD_DARKGRAY); 649 rb->lcd_set_background(LCD_DARKGRAY);
639 draw_hline(0, wvs.width, 0); 650 draw_hline(0, wvs.width, 0);
640 651
@@ -645,13 +656,15 @@ static void wvs_refresh_background(void)
645 rb->lcd_set_drawmode(DRMODE_SOLID); 656 rb->lcd_set_drawmode(DRMODE_SOLID);
646 657
647 if (stream_get_duration() != INVALID_TIMESTAMP) { 658 if (stream_get_duration() != INVALID_TIMESTAMP) {
648 /* Don't know the duration */ 659 /* Draw the movie duration */
649 ts_to_hms(stream_get_duration(), &hms); 660 ts_to_hms(stream_get_duration(), &hms);
650 hms_format(buf, sizeof (buf), &hms); 661 hms_format(buf, sizeof (buf), &hms);
651 draw_putsxy_oriented(wvs.dur_rect.l, wvs.dur_rect.t, buf); 662 draw_putsxy_oriented(wvs.dur_rect.l, wvs.dur_rect.t, buf);
652 } 663 }
664 /* else don't know the duration */
653} 665}
654 666
667/* Refresh the current time display + the progress bar */
655static void wvs_refresh_time(void) 668static void wvs_refresh_time(void)
656{ 669{
657 char buf[32]; 670 char buf[32];
@@ -676,6 +689,7 @@ static void wvs_refresh_time(void)
676#endif 689#endif
677} 690}
678 691
692/* Refresh the volume display area */
679static void wvs_refresh_volume(void) 693static void wvs_refresh_volume(void)
680{ 694{
681 char buf[32]; 695 char buf[32];
@@ -696,6 +710,7 @@ static void wvs_refresh_volume(void)
696#endif 710#endif
697} 711}
698 712
713/* Refresh the status icon */
699static void wvs_refresh_status(void) 714static void wvs_refresh_status(void)
700{ 715{
701 int icon_size = wvs.stat_rect.r - wvs.stat_rect.l; 716 int icon_size = wvs.stat_rect.r - wvs.stat_rect.l;
@@ -738,6 +753,7 @@ static void wvs_refresh_status(void)
738#endif 753#endif
739} 754}
740 755
756/* Update the current status which determines which icon is displayed */
741static bool wvs_update_status(void) 757static bool wvs_update_status(void)
742{ 758{
743 int status; 759 int status;
@@ -748,6 +764,7 @@ static bool wvs_update_status(void)
748 status = WVS_STATUS_STOPPED; 764 status = WVS_STATUS_STOPPED;
749 break; 765 break;
750 case STREAM_PAUSED: 766 case STREAM_PAUSED:
767 /* If paused with a pending resume, coerce it to WVS_STATUS_PLAYING */
751 status = (wvs.auto_refresh & WVS_REFRESH_RESUME) ? 768 status = (wvs.auto_refresh & WVS_REFRESH_RESUME) ?
752 WVS_STATUS_PLAYING : WVS_STATUS_PAUSED; 769 WVS_STATUS_PLAYING : WVS_STATUS_PAUSED;
753 break; 770 break;
@@ -757,6 +774,7 @@ static bool wvs_update_status(void)
757 } 774 }
758 775
759 if (status != wvs.status) { 776 if (status != wvs.status) {
777 /* A refresh is needed */
760 wvs.status = status; 778 wvs.status = status;
761 return true; 779 return true;
762 } 780 }
@@ -764,6 +782,7 @@ static bool wvs_update_status(void)
764 return false; 782 return false;
765} 783}
766 784
785/* Update the current time that will be displayed */
767static void wvs_update_time(void) 786static void wvs_update_time(void)
768{ 787{
769 uint32_t start; 788 uint32_t start;
@@ -771,6 +790,7 @@ static void wvs_update_time(void)
771 wvs.curr_time -= start; 790 wvs.curr_time -= start;
772} 791}
773 792
793/* Refresh various parts of the WVS - showing it if it is hidden */
774static void wvs_refresh(int hint) 794static void wvs_refresh(int hint)
775{ 795{
776 long tick; 796 long tick;
@@ -779,37 +799,48 @@ static void wvs_refresh(int hint)
779 tick = *rb->current_tick; 799 tick = *rb->current_tick;
780 800
781 if (hint == WVS_REFRESH_DEFAULT) { 801 if (hint == WVS_REFRESH_DEFAULT) {
802 /* The default which forces no updates */
782 803
804 /* Redraw the current or possibly extract a new video frame */
783 if ((wvs.auto_refresh & WVS_REFRESH_VIDEO) && 805 if ((wvs.auto_refresh & WVS_REFRESH_VIDEO) &&
784 TIME_AFTER(tick, wvs.print_tick)) { 806 TIME_AFTER(tick, wvs.print_tick)) {
785 wvs.auto_refresh &= ~WVS_REFRESH_VIDEO; 807 wvs.auto_refresh &= ~WVS_REFRESH_VIDEO;
786 stream_draw_frame(false); 808 stream_draw_frame(false);
787 } 809 }
788 810
811 /* Restart playback if the timout was reached */
789 if ((wvs.auto_refresh & WVS_REFRESH_RESUME) && 812 if ((wvs.auto_refresh & WVS_REFRESH_RESUME) &&
790 TIME_AFTER(tick, wvs.resume_tick)) { 813 TIME_AFTER(tick, wvs.resume_tick)) {
791 wvs.auto_refresh &= ~(WVS_REFRESH_RESUME | WVS_REFRESH_VIDEO); 814 wvs.auto_refresh &= ~(WVS_REFRESH_RESUME | WVS_REFRESH_VIDEO);
792 stream_resume(); 815 stream_resume();
793 } 816 }
794 817
818 /* If not visible, return */
795 if (!(wvs.flags & WVS_SHOW)) 819 if (!(wvs.flags & WVS_SHOW))
796 return; 820 return;
797 821
822 /* Hide if the visibility duration was reached */
798 if (TIME_AFTER(tick, wvs.hide_tick)) { 823 if (TIME_AFTER(tick, wvs.hide_tick)) {
799 wvs_show(WVS_HIDE); 824 wvs_show(WVS_HIDE);
800 return; 825 return;
801 } 826 }
802 } else { 827 } else {
828 /* A forced update of some region */
829
830 /* Show if currently invisible */
803 if (!(wvs.flags & WVS_SHOW)) { 831 if (!(wvs.flags & WVS_SHOW)) {
832 /* Avoid call back into this function - it will be drawn */
804 wvs_show(WVS_SHOW | WVS_NODRAW); 833 wvs_show(WVS_SHOW | WVS_NODRAW);
805 hint = WVS_REFRESH_ALL; 834 hint = WVS_REFRESH_ALL;
806 } 835 }
807 836
837 /* Move back timeouts for frame print and hide */
808 wvs.print_tick = tick + wvs.print_delay; 838 wvs.print_tick = tick + wvs.print_delay;
809 wvs.hide_tick = tick + wvs.show_for; 839 wvs.hide_tick = tick + wvs.show_for;
810 } 840 }
811 841
812 if (TIME_AFTER(tick, wvs.next_auto_refresh)) { 842 if (TIME_AFTER(tick, wvs.next_auto_refresh)) {
843 /* Refresh whatever graphical elements are due automatically */
813 wvs.next_auto_refresh = tick + WVS_MIN_UPDATE_INTERVAL; 844 wvs.next_auto_refresh = tick + WVS_MIN_UPDATE_INTERVAL;
814 845
815 if (wvs.auto_refresh & WVS_REFRESH_STATUS) { 846 if (wvs.auto_refresh & WVS_REFRESH_STATUS) {
@@ -824,8 +855,10 @@ static void wvs_refresh(int hint)
824 } 855 }
825 856
826 if (hint == 0) 857 if (hint == 0)
827 return; 858 return; /* No drawing needed */
828 859
860 /* Set basic drawing params that are used. Elements that perform variations
861 * will restore them. */
829 oldfg = rb->lcd_get_foreground(); 862 oldfg = rb->lcd_get_foreground();
830 oldbg = rb->lcd_get_background(); 863 oldbg = rb->lcd_get_background();
831 864
@@ -854,11 +887,13 @@ static void wvs_refresh(int hint)
854 wvs_refresh_status(); 887 wvs_refresh_status();
855 } 888 }
856 889
890 /* Go back to defaults */
857 rb->lcd_setfont(FONT_SYSFIXED); 891 rb->lcd_setfont(FONT_SYSFIXED);
858 rb->lcd_set_foreground(oldfg); 892 rb->lcd_set_foreground(oldfg);
859 rb->lcd_set_background(oldbg); 893 rb->lcd_set_background(oldbg);
860 894
861#ifdef HAVE_LCD_COLOR 895#ifdef HAVE_LCD_COLOR
896 /* Update the dirty rectangle */
862 vo_lock(); 897 vo_lock();
863 898
864 draw_update_rect(wvs.update_rect.l, 899 draw_update_rect(wvs.update_rect.l,
@@ -868,16 +903,19 @@ static void wvs_refresh(int hint)
868 903
869 vo_unlock(); 904 vo_unlock();
870#else 905#else
906 /* Defer update to greylib */
871 grey_deferred_lcd_update(); 907 grey_deferred_lcd_update();
872#endif 908#endif
873} 909}
874 910
911/* Show/Hide the WVS */
875static void wvs_show(unsigned show) 912static void wvs_show(unsigned show)
876{ 913{
877 if (((show ^ wvs.flags) & WVS_SHOW) == 0) 914 if (((show ^ wvs.flags) & WVS_SHOW) == 0)
878 return; 915 return;
879 916
880 if (show & WVS_SHOW) { 917 if (show & WVS_SHOW) {
918 /* Clip away the part of video that is covered */
881 struct vo_rect rc = { 0, 0, SCREEN_WIDTH, wvs.y }; 919 struct vo_rect rc = { 0, 0, SCREEN_WIDTH, wvs.y };
882 920
883 wvs.flags |= WVS_SHOW; 921 wvs.flags |= WVS_SHOW;
@@ -887,6 +925,7 @@ static void wvs_show(unsigned show)
887 if (!(show & WVS_NODRAW)) 925 if (!(show & WVS_NODRAW))
888 wvs_refresh(WVS_REFRESH_ALL); 926 wvs_refresh(WVS_REFRESH_ALL);
889 } else { 927 } else {
928 /* Uncover clipped video area and redraw it */
890 wvs.flags &= ~WVS_SHOW; 929 wvs.flags &= ~WVS_SHOW;
891 930
892 stream_vo_set_clip(NULL); 931 stream_vo_set_clip(NULL);
@@ -904,6 +943,7 @@ static void wvs_show(unsigned show)
904 } 943 }
905} 944}
906 945
946/* Set the current status - update screen if specified */
907static void wvs_set_status(int status) 947static void wvs_set_status(int status)
908{ 948{
909 bool draw = (status & WVS_NODRAW) == 0; 949 bool draw = (status & WVS_NODRAW) == 0;
@@ -1035,6 +1075,7 @@ static int wvs_status(void)
1035 return status; 1075 return status;
1036} 1076}
1037 1077
1078/* Change the current audio volume by a specified amount */
1038static void wvs_set_volume(int delta) 1079static void wvs_set_volume(int delta)
1039{ 1080{
1040 int vol = rb->global_settings->volume; 1081 int vol = rb->global_settings->volume;
@@ -1043,20 +1084,24 @@ static void wvs_set_volume(int delta)
1043 vol += delta; 1084 vol += delta;
1044 1085
1045 if (delta < 0) { 1086 if (delta < 0) {
1087 /* Volume down - clip to lower limit */
1046 limit = rb->sound_min(SOUND_VOLUME); 1088 limit = rb->sound_min(SOUND_VOLUME);
1047 if (vol < limit) 1089 if (vol < limit)
1048 vol = limit; 1090 vol = limit;
1049 } else { 1091 } else {
1092 /* Volume up - clip to upper limit */
1050 limit = rb->sound_max(SOUND_VOLUME); 1093 limit = rb->sound_max(SOUND_VOLUME);
1051 if (vol > limit) 1094 if (vol > limit)
1052 vol = limit; 1095 vol = limit;
1053 } 1096 }
1054 1097
1098 /* Sync the global settings */
1055 if (vol != rb->global_settings->volume) { 1099 if (vol != rb->global_settings->volume) {
1056 rb->sound_set(SOUND_VOLUME, vol); 1100 rb->sound_set(SOUND_VOLUME, vol);
1057 rb->global_settings->volume = vol; 1101 rb->global_settings->volume = vol;
1058 } 1102 }
1059 1103
1104 /* Update the volume display */
1060 wvs_refresh(WVS_REFRESH_VOLUME); 1105 wvs_refresh(WVS_REFRESH_VOLUME);
1061} 1106}
1062 1107
@@ -1079,6 +1124,7 @@ static int wvs_play(uint32_t time)
1079 return retval; 1124 return retval;
1080} 1125}
1081 1126
1127/* Halt playback - pause engine and return logical state */
1082static int wvs_halt(void) 1128static int wvs_halt(void)
1083{ 1129{
1084 int status = stream_pause(); 1130 int status = stream_pause();
@@ -1089,18 +1135,20 @@ static int wvs_halt(void)
1089 status = STREAM_PLAYING; 1135 status = STREAM_PLAYING;
1090 } 1136 }
1091 1137
1138 /* Cancel some auto refreshes - caller will restart them if desired */
1092 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME); 1139 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME);
1093 1140
1094 return status; 1141 return status;
1095} 1142}
1096 1143
1144/* Pause playback if playing */
1097static int wvs_pause(void) 1145static int wvs_pause(void)
1098{ 1146{
1099 unsigned refresh = wvs.auto_refresh; 1147 unsigned refresh = wvs.auto_refresh;
1100 int status = wvs_halt(); 1148 int status = wvs_halt();
1101 1149
1102 if (status == STREAM_PLAYING && (refresh & WVS_REFRESH_RESUME)) { 1150 if (status == STREAM_PLAYING && (refresh & WVS_REFRESH_RESUME)) {
1103 wvs_cancel_refresh(WVS_REFRESH_RESUME); 1151 /* Resume pending - change to a still video frame update */
1104 wvs_schedule_refresh(WVS_REFRESH_VIDEO); 1152 wvs_schedule_refresh(WVS_REFRESH_VIDEO);
1105 } 1153 }
1106 1154
@@ -1109,13 +1157,17 @@ static int wvs_pause(void)
1109 return status; 1157 return status;
1110} 1158}
1111 1159
1160/* Resume playback if halted or paused */
1112static void wvs_resume(void) 1161static void wvs_resume(void)
1113{ 1162{
1163 /* Cancel video and resume auto refresh - the resyc when starting playback
1164 * will perform those tasks */
1114 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME); 1165 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME);
1115 wvs_set_status(WVS_STATUS_PLAYING); 1166 wvs_set_status(WVS_STATUS_PLAYING);
1116 stream_resume(); 1167 stream_resume();
1117} 1168}
1118 1169
1170/* Stop playback - remember the resume point if not already stopped */
1119static void wvs_stop(void) 1171static void wvs_stop(void)
1120{ 1172{
1121 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME); 1173 wvs_cancel_refresh(WVS_REFRESH_VIDEO | WVS_REFRESH_RESUME);
@@ -1125,6 +1177,8 @@ static void wvs_stop(void)
1125 settings.resume_time = stream_get_resume_time(); 1177 settings.resume_time = stream_get_resume_time();
1126} 1178}
1127 1179
1180/* Perform a seek if seeking is possible for this stream - if playing, a delay
1181 * will be inserted before restarting in case the user decides to seek again */
1128static void wvs_seek(int btn) 1182static void wvs_seek(int btn)
1129{ 1183{
1130 int status; 1184 int status;
@@ -1134,6 +1188,7 @@ static void wvs_seek(int btn)
1134 if (!stream_can_seek()) 1188 if (!stream_can_seek())
1135 return; 1189 return;
1136 1190
1191 /* Halt playback - not strictly nescessary but nice */
1137 status = wvs_halt(); 1192 status = wvs_halt();
1138 1193
1139 if (status == STREAM_STOPPED) 1194 if (status == STREAM_STOPPED)
@@ -1146,8 +1201,10 @@ static void wvs_seek(int btn)
1146 else 1201 else
1147 refresh = WVS_REFRESH_VIDEO; /* refresh if paused */ 1202 refresh = WVS_REFRESH_VIDEO; /* refresh if paused */
1148 1203
1204 /* Obtain a new playback point */
1149 time = wvs_ff_rw(btn, refresh); 1205 time = wvs_ff_rw(btn, refresh);
1150 1206
1207 /* Tell engine to resume at that time */
1151 stream_seek(time, SEEK_SET); 1208 stream_seek(time, SEEK_SET);
1152} 1209}
1153 1210