chiark / gitweb /
Disobedience: mention global prefs in manual.
[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 3 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,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU 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, see <http://www.gnu.org/licenses/>.
17  */
18 /** @file disobedience/lookup.c
19  * @brief Disobedience server lookups and caching
20  */
21 #include "disobedience.h"
22
23 static int namepart_lookups_outstanding;
24 static const struct cache_type cachetype_string = { 3600 };
25 static const struct cache_type cachetype_integer = { 3600 };
26
27 /** @brief Called when a namepart lookup has completed or failed
28  *
29  * When there are no lookups in flight a redraw is provoked.  This might well
30  * provoke further lookups.
31  */
32 static void namepart_completed_or_failed(void) {
33   --namepart_lookups_outstanding;
34   if(!namepart_lookups_outstanding)
35     /* When all lookups complete, we update any displays that care */
36     event_raise("lookups-completed", 0);
37 }
38
39 /** @brief Called when a namepart lookup has completed */
40 static void namepart_completed(void *v, const char *err, const char *value) {
41   D(("namepart_completed"));
42   if(err) {
43     gtk_label_set_text(GTK_LABEL(report_label), err);
44     value = "?";
45   }
46   const char *key = v;
47   
48   cache_put(&cachetype_string, key, value);
49   namepart_completed_or_failed();
50 }
51
52 /** @brief Called when a length lookup has completed */
53 static void length_completed(void *v, const char *err, long l) {
54   D(("length_completed"));
55   if(err) {
56     gtk_label_set_text(GTK_LABEL(report_label), err);
57     l = -1;
58   }
59   const char *key = v;
60   long *value;
61   
62   D(("namepart_completed"));
63   value = xmalloc(sizeof *value);
64   *value = l;
65   cache_put(&cachetype_integer, key, value);
66   namepart_completed_or_failed();
67 }
68
69 /** @brief Arrange to fill in a namepart cache entry */
70 static void namepart_fill(const char *track,
71                           const char *context,
72                           const char *part,
73                           const char *key) {
74   D(("namepart_fill %s %s %s %s", track, context, part, key));
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  *
86  * If it is in the cache then just return its value.  If not then look it up
87  * and arrange for the queues to be updated when its value is available. */
88 const char *namepart(const char *track,
89                      const char *context,
90                      const char *part) {
91   char *key;
92   const char *value;
93
94   D(("namepart %s %s %s", track, context, part));
95   byte_xasprintf(&key, "namepart context=%s part=%s track=%s",
96                  context, part, track);
97   value = cache_get(&cachetype_string, key);
98   if(!value) {
99     D(("deferring..."));
100     namepart_fill(track, context, part, key);
101     value = "?";
102   }
103   return value;
104 }
105
106 /** @brief Called from @ref disobedience/properties.c when we know a name part has changed */
107 void namepart_update(const char *track,
108                      const char *context,
109                      const char *part) {
110   char *key;
111
112   byte_xasprintf(&key, "namepart context=%s part=%s track=%s",
113                  context, part, track);
114   /* Only refetch if it's actually in the cache. */
115   if(cache_get(&cachetype_string, key))
116     namepart_fill(track, context, part, key);
117 }
118
119 /** @brief Look up a track length
120  *
121  * If it is in the cache then just return its value.  If not then look it up
122  * and arrange for the queues to be updated when its value is available. */
123 long namepart_length(const char *track) {
124   char *key;
125   const long *value;
126
127   D(("getlength %s", track));
128   byte_xasprintf(&key, "length track=%s", track);
129   value = cache_get(&cachetype_integer, key);
130   if(value)
131     return *value;
132   D(("deferring..."));;
133   ++namepart_lookups_outstanding;
134   D(("namepart_lookups_outstanding -> %d\n", namepart_lookups_outstanding));
135   disorder_eclient_length(client, length_completed, track, key);
136   return -1;
137 }
138
139 /** @brief Resolve a track name
140  *
141  * Returns the supplied track name if it doesn't have the answer yet.
142  */
143 char *namepart_resolve(const char *track) {
144   char *key;
145
146   byte_xasprintf(&key, "resolve track=%s", track);
147   const char *value = cache_get(&cachetype_string, key);
148   if(!value) {
149     D(("deferring..."));
150     ++namepart_lookups_outstanding;
151     D(("namepart_lookups_outstanding -> %d\n", namepart_lookups_outstanding));
152     disorder_eclient_resolve(client, namepart_completed,
153                              track, (void *)key);
154     value = track;
155   }
156   return xstrdup(value);
157 }
158
159 /*
160 Local Variables:
161 c-basic-offset:2
162 comment-column:40
163 fill-column:79
164 indent-tabs-mode:nil
165 End:
166 */