1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
diff --git a/apps/metadata.c b/apps/metadata.c
index efe18a7..def6ad3 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -418,7 +418,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
 {
     const struct afmt_entry *entry;
     int logfd = 0;
-    DEBUGF("Read metadata for %s\n", trackname);
+    //~ DEBUGF("Read metadata for %s\n", trackname);
     if (write_metadata_log)
     {
         logfd = open("/metadata.log", O_WRONLY | O_APPEND | O_CREAT, 0666);
@@ -447,7 +447,7 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
 
     if (!entry->parse_func(fd, id3))
     {
-        DEBUGF("parsing %s failed (format: %s)", trackname, entry->label);
+        //~ DEBUGF("parsing %s failed (format: %s)", trackname, entry->label);
         return false;
     }
 
diff --git a/apps/playback.c b/apps/playback.c
index 1b883b8..8b5c6a9 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -860,13 +860,16 @@ static int shrink_callback(int handle, unsigned hints, void* start, size_t old_s
             audio_reset_buffer_noalloc(start + wanted_size);
             break;
     }
-    if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
+    if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY
+        && filebuflen >= (100<<10))
     {
         if (thread_self() == audio_thread_id)
             audio_start_playback(offset, 0);  /* inline Q_AUDIO_PLAY */
         else
             audio_play(offset);
     }
+    else if (filebuflen < (100<<10))
+        buffer_state = AUDIOBUF_STATE_TRASHED;
 
     return BUFLIB_CB_OK;
 }
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 8d522b1..46818a7 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -222,9 +222,9 @@ struct statefile_header {
 
 /* Pointer to allocated ramcache_header */
 static struct ramcache_header *ramcache_hdr;
+#endif
 /* lock entity to temporarily prevent ramcache_hdr from moving */
 static int move_lock;
-#endif
 
 /** 
  * Full tag entries stored in a temporary file waiting 
@@ -2919,6 +2919,69 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
     return 1;
 }
 
+
+static int tempbuf_handle;
+
+#ifdef HAVE_TC_RAMCACHE
+static void fix_ramcache(void* old_addr, void* new_addr)
+{
+    ptrdiff_t offpos = new_addr - old_addr;
+    for (int i = 0; i < TAG_COUNT; i++)
+        ramcache_hdr->tags[i] += offpos;
+}
+
+#endif
+static int move_cb(int handle, void* current, void* new)
+{
+    if (move_lock > 0 || handle == tempbuf_handle)
+        return BUFLIB_CB_CANNOT_MOVE;
+
+#ifdef HAVE_TC_RAMCACHE
+    fix_ramcache(current, new);
+    ramcache_hdr = new;
+#endif
+    return BUFLIB_CB_OK;
+}
+
+static struct buflib_callbacks ops = {
+    .move_callback = move_cb,
+    .shrink_callback = NULL,
+};
+
+static void allocate_tempbuf(void)
+{
+    /* Yeah, malloc would be really nice now :) */
+#ifdef __PCTOOL__
+    tempbuf_size = 32*1024*1024;
+    tempbuf = malloc(tempbuf_size);
+#else
+    ssize_t avail = audio_buffer_available();
+    /* leave 1MB for audio */
+    avail -= 1<<20;
+    if (avail > 0 && tempbuf_handle == 0)
+    {
+        tempbuf_handle = core_alloc_ex("tc tempbuf", avail, &ops);
+        tempbuf_size = avail;
+        tempbuf = core_get_data(tempbuf_handle);
+    }
+#endif
+}
+
+static void free_tempbuf(void)
+{
+    if (tempbuf_size == 0)
+        return ;
+    
+#ifdef __PCTOOL__
+    free(tempbuf);
+#else
+    if (tempbuf_handle > 0)
+        tempbuf_handle = core_free(tempbuf_handle);
+#endif
+    tempbuf = NULL;
+    tempbuf_size = 0;
+}
+
 static bool commit(void)
 {
     struct tagcache_header tch;
@@ -2995,6 +3058,7 @@ static bool commit(void)
         if (tempbuf_size > 0)
         {
             dircache_buffer_stolen = true;
+            printf("dc buf stolen: %zu\n", tempbuf_size);
         }
     }
 #endif    
@@ -3009,6 +3073,9 @@ static bool commit(void)
         ramcache_buffer_stolen = true;
     }
 #endif
+
+    if (tempbuf_size == 0 && local_allocation)
+        allocate_tempbuf();
     
     /* And finally fail if there are no buffers available. */
     if (tempbuf_size == 0)
@@ -3039,9 +3106,16 @@ static bool commit(void)
             continue;
         
         tc_stat.commit_step++;
+retry:
         ret = build_index(i, &tch, tmpfd);
         if (ret <= 0)
         {
+            if (ret == 0 && tempbuf_handle == 0)
+            {   /* now try really hard to allocate a temp buffer */
+                printf("trying *really* hard...\n");
+                allocate_tempbuf();
+                goto retry;
+            }
             close(tmpfd);
             logf("tagcache failed init");
             if (ret == 0)
@@ -3091,10 +3165,7 @@ static bool commit(void)
     tc_stat.readyvalid = true;
     
     if (local_allocation)
-    {
-        tempbuf = NULL;
-        tempbuf_size = 0;
-    }
+        free_tempbuf();
     
 #ifdef HAVE_DIRCACHE
     /* Rebuild the dircache, if we stole the buffer. */
@@ -3115,33 +3186,6 @@ static bool commit(void)
     return true;
 }
 
-static int tempbuf_handle;
-static void allocate_tempbuf(void)
-{
-    /* Yeah, malloc would be really nice now :) */
-#ifdef __PCTOOL__
-    tempbuf_size = 32*1024*1024;
-    tempbuf = malloc(tempbuf_size);
-#else
-    tempbuf_handle = core_alloc_maximum("tc tempbuf", &tempbuf_size, NULL);
-    tempbuf = core_get_data(tempbuf_handle);
-#endif
-}
-
-static void free_tempbuf(void)
-{
-    if (tempbuf_size == 0)
-        return ;
-    
-#ifdef __PCTOOL__
-    free(tempbuf);
-#else
-    tempbuf_handle = core_free(tempbuf_handle);
-#endif
-    tempbuf = NULL;
-    tempbuf_size = 0;
-}
-
 #ifndef __PCTOOL__
 
 static bool modify_numeric_entry(int masterfd, int idx_id, int tag, long data)
@@ -3848,30 +3892,6 @@ static bool check_event_queue(void)
 #endif
 
 #ifdef HAVE_TC_RAMCACHE
-
-static void fix_ramcache(void* old_addr, void* new_addr)
-{
-    ptrdiff_t offpos = new_addr - old_addr;
-    for (int i = 0; i < TAG_COUNT; i++)
-        ramcache_hdr->tags[i] += offpos;
-}
-
-static int move_cb(int handle, void* current, void* new)
-{
-    (void)handle;
-    if (move_lock > 0)
-        return BUFLIB_CB_CANNOT_MOVE;
-
-    fix_ramcache(current, new);
-    ramcache_hdr = new;
-    return BUFLIB_CB_OK;
-}
-
-static struct buflib_callbacks ops = {
-    .move_callback = move_cb,
-    .shrink_callback = NULL,
-};
-
 static bool allocate_tagcache(void)
 {
     struct master_header tcmh;
@@ -4560,8 +4580,15 @@ void tagcache_build(const char *path)
 #ifdef __PCTOOL__
     free_tempbuf();
 #endif
-    
+
 #ifdef HAVE_TC_RAMCACHE
+    /* Allocate space for the tagcache if found on disk. */
+    if (global_settings.tagcache_ram && !tc_stat.ramcache)
+    {
+        allocate_tagcache();
+        load_tagcache();
+    }
+
     if (ramcache_hdr)
     {
         /* Import runtime statistics if we just initialized the db. */