chiark / gitweb /
Playing checkbox in Disobedience choose tab is now only visible for
[disorder] / disobedience / lookup.c
1 /*
2  * This file is part of DisOrder
3  * Copyright (C) 2008 Richard Kettlewell
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18  * USA
19  */
20 #include "disobedience.h"
21
22 static int namepart_lookups_outstanding;
23 static const struct cache_type cachetype_string = { 3600 };
24 static const struct cache_type cachetype_integer = { 3600 };
25
26 /** @brief Called when a namepart lookup has completed or failed
27  *
28  * When there are no lookups in flight a redraw is provoked.  This might well
29  * provoke further lookups.
30  */
31 static void namepart_completed_or_failed(void) {
32   --namepart_lookups_outstanding;
33   if(!namepart_lookups_outstanding)
34     /* When all lookups complete, we update any displays that care */
35     event_raise("lookups-completed", 0);
36 }
37
38 /** @brief Called when a namepart lookup has completed */
39 static void namepart_completed(void *v, const char *error, const char *value) {
40   D(("namepart_completed"));
41   if(error) {
42     gtk_label_set_text(GTK_LABEL(report_label), error);
43     value = "?";
44   }
45   const char *key = v;
46   
47   cache_put(&cachetype_string, key, value);
48   namepart_completed_or_failed();
49 }
50
51 /** @brief Called when a length lookup has completed */
52 static void length_completed(void *v, const char *error, long l) {
53   D(("length_completed"));
54   if(error) {
55     gtk_label_set_text(GTK_LABEL(report_label), error);
56     l = -1;
57   }
58   const char *key = v;
59   long *value;
60   
61   D(("namepart_completed"));
62   value = xmalloc(sizeof *value);
63   *value = l;
64   cache_put(&cachetype_integer, key, value);
65   namepart_completed_or_failed();
66 }
67
68 /** @brief Arrange to fill in a namepart cache entry */
69 static void namepart_fill(const char *track,
70                           const char *context,
71                           const char *part,
72                           const char *key) {
73   D(("namepart_fill %s %s %s %s", track, context, part, key));
74   /* We limit the total number of lookups in flight */
75   ++namepart_lookups_outstanding;
76   D(("namepart_lookups_outstanding -> %d\n", namepart_lookups_outstanding));
77   disorder_eclient_namepart(client, namepart_completed,
78                             track, context, part, (void *)key);
79 }
80
81 /** @brief Look up a namepart
82  * @param track Track name
83  * @param context Context
84  * @param part Name part
85  * @param lookup If nonzero, will schedule a lookup for unknown values
86  *
87  * If it is in the cache then just return its value.  If not then look it up
88  * and arrange for the queues to be updated when its value is available. */
89 const char *namepart(const char *track,
90                      const char *context,
91                      const char *part) {
92   char *key;
93   const char *value;
94
95   D(("namepart %s %s %s", track, context, part));
96   byte_xasprintf(&key, "namepart context=%s part=%s track=%s",
97                  context, part, track);
98   value = cache_get(&cachetype_string, key);
99   if(!value) {
100     D(("deferring..."));
101     namepart_fill(track, context, part, key);
102     value = "?";
103   }
104   return value;
105 }
106
107 /** @brief Called from @ref disobedience/properties.c when we know a name part has changed */
108 void namepart_update(const char *track,
109                      const char *context,
110                      const char *part) {
111   char *key;
112
113   byte_xasprintf(&key, "namepart context=%s part=%s track=%s",
114                  context, part, track);
115   /* Only refetch if it's actually in the cache. */
116   if(cache_get(&cachetype_string, key))
117     namepart_fill(track, context, part, key);
118 }
119
120 /** @brief Look up a track length
121  *
122  * If it is in the cache then just return its value.  If not then look it up
123  * and arrange for the queues to be updated when its value is available. */
124 long namepart_length(const char *track) {
125   char *key;
126   const long *value;
127
128   D(("getlength %s", track));
129   byte_xasprintf(&key, "length track=%s", track);
130   value = cache_get(&cachetype_integer, key);
131   if(value)
132     return *value;
133   D(("deferring..."));;
134   ++namepart_lookups_outstanding;
135   D(("namepart_lookups_outstanding -> %d\n", namepart_lookups_outstanding));
136   disorder_eclient_length(client, length_completed, track, key);
137   return -1;
138 }
139
140
141 /*
142 Local Variables:
143 c-basic-offset:2
144 comment-column:40
145 fill-column:79
146 indent-tabs-mode:nil
147 End:
148 */