1 /*
2     Waveform seekbar plugin for the DeaDBeeF audio player
3 
4     Copyright (C) 2014 Christian Boxdörfer <christian.boxdoerfer@posteo.de>
5 
6     Based on sndfile-tools waveform by Erik de Castro Lopo.
7         waveform.c - v1.04
8         Copyright (C) 2007-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
9         Copyright (C) 2012 Robin Gareus <robin@gareus.org>
10         Copyright (C) 2013 driedfruit <driedfruit@mindloop.net>
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 program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21 
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25 */
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <math.h>
33 #include <fcntl.h>
34 
35 #include <deadbeef/deadbeef.h>
36 
37 #include "waveform.h"
38 #include "utils.h"
39 
40 typedef struct cache_query_s
41 {
42     char *fname;
43     struct cache_query_s *next;
44 } cache_query_t;
45 
46 static uintptr_t mutex = 0;
47 static cache_query_t *queue;
48 static cache_query_t *queue_tail;
49 
50 int
check_dir(const char * dir,mode_t mode)51 check_dir (const char *dir, mode_t mode)
52 {
53     char *tmp = strdup (dir);
54     char *slash = tmp;
55     struct stat stat_buf;
56     do
57     {
58         slash = strstr (slash+1, "/");
59         if (slash)
60             *slash = 0;
61         if (-1 == stat (tmp, &stat_buf))
62         {
63             if (0 != mkdir (tmp, mode))
64             {
65                 free (tmp);
66                 return 0;
67             }
68         }
69         if (slash)
70             *slash = '/';
71     } while (slash);
72     free (tmp);
73     return 1;
74 }
75 
76 int
queue_add(const char * fname)77 queue_add (const char *fname)
78 {
79     if (!mutex) {
80         mutex = deadbeef->mutex_create ();
81     }
82     deadbeef->mutex_lock (mutex);
83     for (cache_query_t *q = queue; q; q = q->next) {
84         if (!strcmp (fname, q->fname)) {
85             // already queued
86             trace ("waveform: already queued. (%s)\n",fname);
87             deadbeef->mutex_unlock (mutex);
88             return 0;
89         }
90     }
91     cache_query_t *q = malloc (sizeof (cache_query_t));
92     memset (q, 0, sizeof (cache_query_t));
93     q->fname = strdup (fname);
94     if (queue_tail) {
95         queue_tail->next = q;
96         queue_tail = q;
97     }
98     else {
99         queue = queue_tail = q;
100     }
101     trace ("waveform: queued. (%s)\n",fname);
102     deadbeef->mutex_unlock (mutex);
103     return 1;
104 }
105 
106 void
queue_pop(const char * fname)107 queue_pop (const char *fname)
108 {
109     deadbeef->mutex_lock (mutex);
110     cache_query_t *next = NULL;
111     for (cache_query_t *q = queue; q; q = q->next) {
112         if (!strcmp (fname, q->fname)) {
113             next = q->next;
114             if (q->fname) {
115                 trace ("waveform: removed from queue. (%s)\n",q->fname);
116                 free (q->fname);
117             }
118             free (q);
119             break;
120         }
121     }
122     queue = next;
123     if (!queue) {
124         queue_tail = NULL;
125     }
126     deadbeef->mutex_unlock (mutex);
127 }
128