summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/sort.c207
-rw-r--r--apps/plugins/viewers.config1
2 files changed, 208 insertions, 0 deletions
diff --git a/apps/plugins/sort.c b/apps/plugins/sort.c
new file mode 100644
index 0000000000..ae59bd0121
--- /dev/null
+++ b/apps/plugins/sort.c
@@ -0,0 +1,207 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Linus Nielsen Feltzing
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "plugin.h"
20
21/****************************************************************************
22 * Buffer handling:
23 *
24 * We allocate the MP3 buffer for storing the text to be sorted, and then
25 * search the buffer for newlines and store an array of character pointers
26 * to the strings.
27 *
28 * The pointer array grows from the top of the buffer and downwards:
29 *
30 * |-------------|
31 * | pointers[2] |--------|
32 * | pointers[1] |------| |
33 * | pointers[0] |----| | |
34 * |-------------| | | |
35 * | | | | |
36 * | | | | |
37 * | free space | | | |
38 * | | | | |
39 * | | | | |
40 * |-------------| | | |
41 * | | | | |
42 * | line 3\0 |<---| | |
43 * | line 2\0 |<-----| |
44 * | line 1\0 |<-------|
45 * |-------------|
46 *
47 * The advantage of this method is that we optimize the buffer usage.
48 *
49 * The disadvantage is that the string pointers will be loaded in reverse
50 * order. We therefore sort the strings in reverse order as well, so we
51 * don't have to sort an already sorted buffer.
52 ****************************************************************************/
53
54/***************************************************************************
55 * TODO: Implement a merge sort for files larger than the buffer
56 ****************************************************************************/
57
58static struct plugin_api* rb;
59
60int buf_size;
61static char *filename;
62static int num_entries;
63static char **pointers;
64static char *stringbuffer;
65static char crlf[2] = "\r\n";
66
67/* Compare function for sorting backwards */
68static int compare(const void* p1, const void* p2)
69{
70 char *s1 = *(char **)p1;
71 char *s2 = *(char **)p2;
72
73 return rb->strcmp(s2, s1);
74}
75
76static void sort_buffer(void)
77{
78 rb->qsort(pointers, num_entries, sizeof(char *), compare);
79}
80
81int read_buffer(int offset)
82{
83 int fd;
84 char *buf_ptr;
85 char *tmp_ptr;
86 int readsize;
87
88 fd = rb->open(filename, O_RDONLY);
89 if(fd < 0)
90 return 10 * fd - 1;
91
92 /* Fill the buffer from the file */
93 rb->lseek(fd, offset, SEEK_SET);
94 readsize = rb->read(fd, stringbuffer, buf_size);
95 rb->close(fd);
96
97 if(readsize < 0)
98 return readsize * 10 - 2;
99
100 /* Temporary fix until we can do merged sorting */
101 if(readsize == buf_size)
102 return buf_size; /* File too big */
103
104 buf_ptr = stringbuffer;
105 num_entries = 0;
106
107 do {
108 tmp_ptr = buf_ptr;
109 while(*buf_ptr != '\n' && buf_ptr < (char *)pointers) {
110 /* Terminate the string with CR... */
111 if(*buf_ptr == '\r')
112 *buf_ptr = 0;
113 buf_ptr++;
114 }
115 /* ...and with LF */
116 if(*buf_ptr == '\n')
117 *buf_ptr = 0;
118 else {
119 return tmp_ptr - stringbuffer; /* Buffer is full, return
120 the point to resume at */
121 }
122
123 pointers--;
124 *pointers = tmp_ptr;
125 num_entries++;
126 buf_ptr++;
127 } while(buf_ptr < stringbuffer + readsize);
128
129 return 0;
130}
131
132static int write_file(void)
133{
134 char tmpfilename[MAX_PATH+1];
135 int fd;
136 int i;
137 int rc;
138
139 /* Create a temporary file */
140 rb->snprintf(tmpfilename, MAX_PATH+1, "%s.tmp", filename);
141 fd = rb->creat(tmpfilename, 0);
142 if(fd < 0)
143 return 10 * fd - 1;
144
145 /* Write the sorted strings, with appended CR/LF, to the temp file,
146 in reverse order */
147 for(i = num_entries-1;i >= 0;i--) {
148 rc = rb->write(fd, pointers[i], rb->strlen(pointers[i]));
149 if(rc < 0) {
150 rb->close(fd);
151 return 10 * rc - 2;
152 }
153
154 rc = rb->write(fd, crlf, 2);
155 if(rc < 0) {
156 rb->close(fd);
157 return 10 * rc - 3;
158 }
159 }
160
161 rb->close(fd);
162
163 /* Remove the original file */
164 rc = rb->remove(filename);
165 if(rc < 0) {
166 return 10 * rc - 4;
167 }
168
169 /* Replace the old file with the new */
170 rc = rb->rename(tmpfilename, filename);
171 if(rc < 0) {
172 return 10 * rc - 5;
173 }
174 return 0;
175}
176
177enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
178{
179 char *buf;
180 int rc;
181 TEST_PLUGIN_API(api);
182
183 filename = (char *)parameter;
184
185 rb = api;
186
187 buf = rb->plugin_get_mp3_buffer(&buf_size); /* start munching memory */
188
189 stringbuffer = buf;
190 pointers = (char **)(buf + buf_size - sizeof(int));
191
192 rc = read_buffer(0);
193 if(rc == 0) {
194 sort_buffer();
195 rc = write_file();
196 if(rc < 0) {
197 rb->splash(HZ, true, "Can't write file: %d", rc);
198 }
199 } else {
200 if(rc < 0)
201 rb->splash(HZ, true, "Can't read file: %d", rc);
202 else
203 rb->splash(HZ, true, "The file is too big");
204 }
205
206 return PLUGIN_OK;
207}
diff --git a/apps/plugins/viewers.config b/apps/plugins/viewers.config
index 2b1d52766b..a04c1640a5 100644
--- a/apps/plugins/viewers.config
+++ b/apps/plugins/viewers.config
@@ -5,3 +5,4 @@ ucl,rockbox_flash.rock,2A 7F 41 41 7F 2A
5rvf,video.rock,5D 7F 5D 7F 5D 7F 5rvf,video.rock,5D 7F 5D 7F 5D 7F
6mp3,vbrfix.rock,10 08 58 38 04 02 6mp3,vbrfix.rock,10 08 58 38 04 02
7m3u,search.rock,00 00 00 00 00 00 7m3u,search.rock,00 00 00 00 00 00
8txt,sort.rock, 00 00 00 00 00 00