A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Marcin Bukat
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "plugin.h"
23#include "lcd.h"
24#include <lib/pluginlib_bmp.h>
25#include "../imageviewer.h"
26#include "ppm_decoder.h"
27#include "bmp.h"
28
29static char print[32]; /* use a common snprintf() buffer */
30
31/* decompressed image in the possible sizes (1,2,4,8), wasting the other */
32static unsigned char *disp[9];
33static unsigned char *disp_buf;
34static struct ppm_info ppm;
35
36#if defined(HAVE_LCD_COLOR)
37#define resize_bitmap smooth_resize_bitmap
38#else
39#define resize_bitmap grey_resize_bitmap
40#endif
41
42#if defined(USEGSLIB) && (CONFIG_PLATFORM & PLATFORM_HOSTED)
43/* hack: fix error "undefined reference to `_grey_info'". */
44GREY_INFO_STRUCT
45#endif /* USEGSLIB */
46
47static void draw_image_rect(struct image_info *info,
48 int x, int y, int width, int height)
49{
50 unsigned char **pdisp = (unsigned char **)info->data;
51
52#ifdef HAVE_LCD_COLOR
53 rb->lcd_bitmap_part((fb_data *)*pdisp, info->x + x, info->y + y,
54 STRIDE(SCREEN_MAIN, info->width, info->height),
55 x + MAX(0, (LCD_WIDTH-info->width)/2),
56 y + MAX(0, (LCD_HEIGHT-info->height)/2),
57 width, height);
58#else
59 mylcd_ub_gray_bitmap_part(*pdisp,
60 info->x + x, info->y + y, info->width,
61 x + MAX(0, (LCD_WIDTH-info->width)/2),
62 y + MAX(0, (LCD_HEIGHT-info->height)/2),
63 width, height);
64#endif
65}
66
67static int img_mem(int ds)
68{
69
70#ifdef USEGSLIB
71 return (ppm.x/ds) * (ppm.y/ds);
72#else
73 return (ppm.x/ds) * (ppm.y/ds) * FB_DATA_SZ;
74#endif
75}
76
77static int load_image(char *filename, struct image_info *info,
78 unsigned char *buf, ssize_t *buf_size,
79 int offset, int filesize)
80{
81 int fd;
82 int rc = PLUGIN_OK;
83 long time = 0; /* measured ticks */
84 int w, h; /* used to center output */
85
86 unsigned char *memory, *memory_max;
87 size_t memory_size;
88
89 /* cleanup */
90 memset(&disp, 0, sizeof(disp));
91
92 /* align buffer */
93 memory = (unsigned char *)((intptr_t)(buf + 3) & ~3);
94 memory_max = (unsigned char *)((intptr_t)(memory + *buf_size) & ~3);
95 memory_size = memory_max - memory;
96
97 fd = rb->open(filename, O_RDONLY);
98 if (fd < 0)
99 {
100 rb->splashf(HZ, "err opening %s: %d", filename, fd);
101 return PLUGIN_ERROR;
102 }
103
104 if (offset)
105 {
106 rb->lseek(fd, offset, SEEK_SET);
107 }
108 else
109 {
110 filesize = rb->filesize(fd);
111 }
112 DEBUGF("reading file '%s'\n", filename);
113
114 if (!iv->running_slideshow)
115 {
116 rb->lcd_puts(0, 0, rb->strrchr(filename,'/')+1);
117 rb->lcd_putsf(0, 1, "loading %zu bytes", filesize);
118 rb->lcd_update();
119 }
120
121 /* init decoder struct */
122 ppm.buf = memory;
123 ppm.buf_size = memory_size;
124
125 /* the actual decoding */
126 time = *rb->current_tick;
127#ifdef HAVE_ADJUSTABLE_CPU_FREQ
128 rb->cpu_boost(true);
129 rc = read_ppm(fd, &ppm);
130 rb->cpu_boost(false);
131#else
132 rc = read_ppm(fd, &ppm);
133#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
134 time = *rb->current_tick - time;
135
136 rb->close(fd);
137
138 if (rc != PLUGIN_OK)
139 {
140 return rc;
141 }
142
143 if (!iv->running_slideshow)
144 {
145 rb->snprintf(print, sizeof(print), " %ld.%02ld sec ", time/HZ, time%HZ);
146 rb->lcd_getstringsize(print, &w, &h); /* centered in progress bar */
147 rb->lcd_putsxy((LCD_WIDTH - w)/2, LCD_HEIGHT - h, print);
148 rb->lcd_update();
149 }
150
151 info->x_size = ppm.x;
152 info->y_size = ppm.y;
153
154 ppm.native_img_size = (ppm.native_img_size + 3) & ~3;
155 disp_buf = buf + ppm.native_img_size;
156 *buf_size = memory_max - disp_buf;
157
158 return PLUGIN_OK;
159}
160
161static int get_image(struct image_info *info, int frame, int ds)
162{
163 (void)frame;
164 unsigned char **p_disp = &disp[ds]; /* short cut */
165 struct ppm_info *p_ppm = &ppm;
166
167 info->width = ppm.x / ds;
168 info->height = ppm.y / ds;
169 info->data = p_disp;
170
171 if (*p_disp != NULL)
172 {
173 /* we still have it */
174 return PLUGIN_OK;
175 }
176
177 /* assign image buffer */
178 if (ds > 1)
179 {
180 if (!iv->running_slideshow)
181 {
182 rb->lcd_putsf(0, 3, "resizing %d*%d", info->width, info->height);
183 rb->lcd_update();
184 }
185
186 struct bitmap bmp_src, bmp_dst;
187 int size = img_mem(ds);
188
189 if (disp_buf + size >= p_ppm->buf + p_ppm->buf_size)
190 {
191 /* have to discard the current */
192 int i;
193 for (i=1; i<=8; i++)
194 disp[i] = NULL; /* invalidate all bitmaps */
195
196 /* start again from the beginning of the buffer */
197 disp_buf = p_ppm->buf + p_ppm->native_img_size;
198 }
199
200 *p_disp = disp_buf;
201 disp_buf += size;
202
203 bmp_src.width = ppm.x;
204 bmp_src.height = ppm.y;
205 bmp_src.data = ppm.buf;
206
207 bmp_dst.width = info->width;
208 bmp_dst.height = info->height;
209 bmp_dst.data = *p_disp;
210#ifdef HAVE_ADJUSTABLE_CPU_FREQ
211 rb->cpu_boost(true);
212 resize_bitmap(&bmp_src, &bmp_dst);
213 rb->cpu_boost(false);
214#else
215 resize_bitmap(&bmp_src, &bmp_dst);
216#endif /*HAVE_ADJUSTABLE_CPU_FREQ*/
217 }
218 else
219 {
220 *p_disp = p_ppm->buf;
221 }
222
223 return PLUGIN_OK;
224}
225
226const struct image_decoder image_decoder = {
227 true,
228 img_mem,
229 load_image,
230 get_image,
231 draw_image_rect,
232};
233
234IMGDEC_HEADER