Source code: jreceiver/client/rio/servlet/RioHostTags.java
1 /* $Header: /cvsroot/jreceiver/jreceiver/src/jreceiver/client/rio/servlet/RioHostTags.java,v 1.7 2002/12/29 00:44:07 reedesau Exp $ */
2
3 package jreceiver.client.rio.servlet;
4
5 import java.io.*;
6 import javax.servlet.*;
7 import javax.servlet.http.*;
8
9 import org.apache.commons.logging.*;
10
11 import jreceiver.client.common.servlet.*;
12 import jreceiver.client.rio.RioLauncher;
13 import jreceiver.common.rec.source.Source;
14 import jreceiver.common.rpc.RpcException;
15 import jreceiver.common.rpc.RpcFactory;
16 import jreceiver.common.rpc.TagEncoder;
17 import jreceiver.util.HexDump;
18
19 /**
20 * Servlet answering 'tags' requests from Rio Server.
21 * <p>
22 * Called by the server (via the <code>service</code> method) to
23 * allow a servlet to handle a GET request.
24 * <p>
25 * Some sample URLs:
26 * <p>
27 * http://.../tags
28 * <p>
29 * It is asking for a simple list of available tags:
30 * <p>
31 * fid
32 * title
33 * artist
34 * source
35 * year
36 * comment
37 * length
38 * type
39 * path
40 * genre
41 * bitrate
42 * playlist
43 * codec
44 * offset
45 * duration
46 * tracknr
47 * <p>
48 * If it asks for the special 0x100 file id...
49 * <p>
50 * http://.../tags/100
51 * <p>
52 * where '100' is a hex number representing the fileid for
53 * the default playlist, which consists of all tracks. Send
54 * back a description of that "All Tracks" playlist.
55 * <p>
56 * Otherwise it will ask for tag info for a specific tune or playlist
57 * <p>
58 * http://.../tags/2b0
59 * <p>
60 * where '2b0' is a hex number representing the src id for
61 * that tune or playlist.
62 *
63 * @author Reed Esau
64 * @version $Revision: 1.7 $ $Date: 2002/12/29 00:44:07 $
65 */
66 public class RioHostTags extends RioHostBase {
67
68 // The following key_ids are used as field identifiers
69 // by the Rio when decoding binary tags.
70 //
71 // Note that they do NOT correspond to the MessageFormatB
72 // field arguments.
73 public static final int KEY_SRC_ID = 0x00;
74 public static final int KEY_TITLE = 0x01;
75 public static final int KEY_ARTIST = 0x02;
76 public static final int KEY_ALBUM = 0x03;
77 public static final int KEY_YEAR = 0x04;
78 public static final int KEY_COMMENT = 0x05;
79 public static final int KEY_FILESIZE = 0x06;
80 public static final int KEY_SRCTYPE = 0x07;
81 public static final int KEY_FILEPATH = 0x08;
82 public static final int KEY_GENRE = 0x09;
83 public static final int KEY_BITRATE = 0x0A;
84 public static final int KEY_PLAYLIST = 0x0B;
85 public static final int KEY_CODEC = 0x0C;
86 public static final int KEY_DATA_OFFSET = 0x0D;
87 public static final int KEY_DURATION = 0x0E;
88 public static final int KEY_TRACKNO = 0x0F;
89
90 /**
91 * the server which hosts the data
92 */
93 protected TagEncoder tag_rpc;
94
95 /**
96 * Create the pattern for the calls to MessageFormatB to encode tune
97 * tags for the Rio.
98 */
99 protected static byte[] tune_pattern = null;
100 static {
101 try {
102 ByteArrayOutputStream buf = new ByteArrayOutputStream();
103 buf.write(KEY_ARTIST);
104 buf.write( ("{"+TagEncoder.TAG_ARTIST+",string,pp}").getBytes() );
105 buf.write(KEY_BITRATE);
106 buf.write( ("{"+TagEncoder.TAG_BITRATE+",string,pp,p=fs}").getBytes() ); // prefix by fs
107 buf.write(KEY_CODEC);
108 buf.write( ("{"+TagEncoder.TAG_CODEC+",string,pp}").getBytes() );
109 buf.write(KEY_DURATION);
110 buf.write( ("{"+TagEncoder.TAG_DURATION+",string,pp}").getBytes() );
111 buf.write(KEY_SRC_ID);
112 buf.write( ("{"+TagEncoder.TAG_SRC_ID+",string,pp}").getBytes() );
113 buf.write(KEY_GENRE);
114 buf.write( ("{"+TagEncoder.TAG_GENRE+",string,pp}").getBytes() );
115 buf.write(KEY_FILESIZE);
116 buf.write( ("{"+TagEncoder.TAG_FILESIZE+",string,pp}").getBytes() );
117 buf.write(KEY_FILEPATH);
118 buf.write( ("{"+TagEncoder.TAG_FILEPATH+",string,pp}").getBytes() );
119 buf.write(KEY_TITLE);
120 buf.write( ("{"+TagEncoder.TAG_TITLE+",string,pp}").getBytes() );
121 buf.write(KEY_ALBUM);
122 buf.write( ("{"+TagEncoder.TAG_ALBUM+",string,pp}").getBytes() );
123 buf.write(KEY_TRACKNO);
124 buf.write( ("{"+TagEncoder.TAG_TRACKNO+",string,pp}").getBytes() );
125 buf.write(KEY_SRCTYPE);
126 buf.write(4); // length of 'tune'
127 buf.write( "tune".getBytes() );
128 buf.write(0xFF);
129 tune_pattern = buf.toByteArray();
130 }
131 catch (IOException ignored) {
132 }
133 }
134
135 /**
136 * Create the pattern for the calls to MessageFormatB to encode
137 * playlist tags for the Rio.
138 */
139 protected static byte[] playlist_pattern = null;
140 static {
141 final byte[] pl = "playlist".getBytes();
142 try {
143 ByteArrayOutputStream buf = new ByteArrayOutputStream();
144 buf.write(KEY_SRC_ID);
145 buf.write( ("{"+TagEncoder.TAG_SRC_ID+",string,pp}").getBytes() );
146 buf.write(KEY_TITLE);
147 buf.write( ("{"+TagEncoder.TAG_TITLE+",string,pp}").getBytes() );
148 buf.write(KEY_SRCTYPE);
149 buf.write( pl.length );
150 buf.write( pl );
151 buf.write(KEY_FILESIZE);
152 buf.write( ("{"+TagEncoder.TAG_COUNT_X_4+",string,pp}").getBytes() );
153 buf.write(0xFF);
154 playlist_pattern = buf.toByteArray();
155 }
156 catch (IOException ignored) {
157 }
158 }
159
160 /**
161 */
162 public void init() throws ServletException {
163 super.init();
164
165 try {
166 tag_rpc = RpcFactory.newTagEncoder();
167 }
168 catch (RpcException e) {
169 throw new ServletException("problem contacting remote server", e);
170 }
171 }
172
173
174 /**
175 * subclasses must define this
176 */
177 protected void handleRequest(HttpServletRequest req,
178 HttpServletResponse resp,
179 int src_id)
180 throws ServletException, IOException, RpcException {
181
182 BaseResponseWriter writer = null;
183 try {
184 if ( src_id == 0x100 || src_id >= Source.MIN_SRC_ID ) {
185 if (log.isDebugEnabled())
186 log.debug("handleRequest: src_id=" + src_id);
187
188 int driver_id = RioLauncher.getDriverId();
189
190 // encode binary tag info for tune or playlist
191 writer = new ResponseStreamWriter();
192 byte[] ar = tag_rpc.encodeTag(src_id, driver_id, tune_pattern, playlist_pattern);
193
194 if (log.isDebugEnabled ())
195 log.debug(HexDump.dumpHexData("handleRequest", ar));
196
197 writer.write(ar);
198 }
199 else { // no src_id provided
200 // encode file descriptors as plain text
201 writer = new ResponseWriter();
202 writer.write("fid\n");
203 writer.write("title\n");
204 writer.write("artist\n");
205 writer.write("source\n");
206 writer.write("year\n");
207 writer.write("comment\n");
208 writer.write("length\n");
209 writer.write("type\n");
210 writer.write("path\n");
211 writer.write("genre\n");
212 writer.write("bitrate\n");
213 writer.write("playlist\n");
214 writer.write("codec\n");
215 writer.write("offset\n");
216 writer.write("duration\n");
217 writer.write("tracknr\n");
218 }
219
220 writer.respond(resp);
221 }
222 finally {
223 if (writer != null)
224 writer.close();
225 }
226 }
227
228 /**
229 * DON'T implicitly fail if no src_id is provided in the * query
230 */
231 protected boolean requireMfileId() {
232 return false;
233 }
234
235 //
236 // internal constants
237 //
238
239 /**
240 * logging sink
241 */
242 protected static Log log = LogFactory.getLog(RioHostTags.class);
243 }
244
245
246 /*
247 JRECEIVER MODIFIED BSD LICENSE
248
249 Copyright (c) 2001-2002, Reed Esau (reed.esau@pobox.com) All rights reserved.
250
251 Redistribution and use in source and binary forms, with or without
252 modification, are permitted provided that the following conditions are
253 met:
254
255 Redistributions of source code must retain the above copyright notice,
256 this list of conditions and the following disclaimer.
257
258 Redistributions in binary form must reproduce the above copyright notice,
259 this list of conditions and the following disclaimer in the documentation
260 and/or other materials provided with the distribution.
261
262 Neither the name of the JReceiver Project
263 (http://jreceiver.sourceforge.net) nor the names of its contributors may
264 be used to endorse or promote products derived from this software without
265 specific prior written permission.
266
267 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
268 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
269 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
270 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
271 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
272 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
273 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
274 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
275 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
276 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
277 POSSIBILITY OF SUCH DAMAGE.
278 */
279