1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Gilles Roux
12 * 2010 Yoshihisa Uchida
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
24 #include "tv_preferences.h"
25 #include "tv_reader.h"
27 #if PLUGIN_BUFFER_SIZE < 0x10000
28 #define TV_MIN_BLOCK_SIZE 0x800
30 #define TV_MIN_BLOCK_SIZE 0x1000
34 #define BOM "\xef\xbb\xbf"
39 static off_t file_pos
;
40 static off_t start_file_pos
;
42 static off_t file_size
;
44 static unsigned char *reader_buffer
;
45 static ssize_t buffer_size
;
46 static ssize_t block_size
;
48 static ssize_t buf_pos
;
49 static ssize_t read_size
;
51 off_t
tv_get_file_size(void)
58 return (file_pos
+ buf_pos
>= file_size
);
61 off_t
tv_get_current_file_pos(void)
63 return file_pos
+ buf_pos
;
66 const unsigned char *tv_get_buffer(ssize_t
*bufsize
)
68 *bufsize
= read_size
- buf_pos
;
69 return reader_buffer
+ buf_pos
;
72 static ssize_t
tv_read(unsigned char *buf
, ssize_t reqsize
)
74 if (buf
- reader_buffer
+ reqsize
> buffer_size
)
75 reqsize
= buffer_size
- (buf
- reader_buffer
);
77 return rb
->read(fd
, buf
, reqsize
);
80 void tv_seek(off_t offset
, int whence
)
87 if (offset
>= file_pos
&& offset
< file_pos
+ read_size
)
89 buf_pos
= offset
- file_pos
;
97 if (buf_pos
>= 0 && buf_pos
< read_size
)
99 if (buf_pos
> block_size
)
101 buf_pos
-= block_size
;
102 file_pos
+= block_size
;
103 size
= read_size
- block_size
;
104 rb
->memcpy(reader_buffer
, reader_buffer
+ block_size
, size
);
105 read_size
= tv_read(reader_buffer
+ block_size
, block_size
);
121 if (whence
== SEEK_SET
)
125 else if (file_pos
> file_size
)
126 file_pos
= file_size
;
128 rb
->lseek(fd
, file_pos
+ start_file_pos
, SEEK_SET
);
130 read_size
= tv_read(reader_buffer
, buffer_size
);
134 static int tv_change_preferences(const struct tv_preferences
*oldp
)
136 bool change_file
= false;
138 /* open the new file */
139 if (oldp
== NULL
|| rb
->strcmp(oldp
->file_name
, preferences
->file_name
))
144 fd
= rb
->open(preferences
->file_name
, O_RDONLY
);
146 return TV_CALLBACK_ERROR
;
148 file_size
= rb
->filesize(fd
);
153 * When a file is UTF-8 file with BOM, if encoding is UTF-8,
154 * then file size decreases only BOM_SIZE.
156 if (change_file
|| oldp
->encoding
!= preferences
->encoding
)
158 int old_start_file_pos
= start_file_pos
;
159 int delta_start_file_pos
;
160 off_t cur_file_pos
= file_pos
+ buf_pos
;
167 if (preferences
->encoding
== UTF_8
)
169 unsigned char bom
[BOM_SIZE
];
171 rb
->lseek(fd
, 0, SEEK_SET
);
172 rb
->read(fd
, bom
, BOM_SIZE
);
173 if (rb
->memcmp(bom
, BOM
, BOM_SIZE
) == 0)
174 start_file_pos
= BOM_SIZE
;
177 delta_start_file_pos
= old_start_file_pos
- start_file_pos
;
178 file_size
+= delta_start_file_pos
;
179 tv_seek(cur_file_pos
+ delta_start_file_pos
, SEEK_SET
);
182 return TV_CALLBACK_OK
;
185 bool tv_init_reader(unsigned char **buf
, size_t *size
)
187 if (*size
< 2 * TV_MIN_BLOCK_SIZE
)
190 block_size
= *size
/ 2;
191 buffer_size
= 2 * block_size
;
192 reader_buffer
= *buf
;
195 *size
-= buffer_size
;
197 tv_add_preferences_change_listner(tv_change_preferences
);
202 void tv_finalize_reader(void)