View Javadoc

1   package org.rpi.mplayer;
2   
3   import java.io.BufferedReader;
4   import java.io.IOException;
5   import java.io.InputStreamReader;
6   import java.text.NumberFormat;
7   import java.text.ParseException;
8   import java.util.regex.Pattern;
9   import org.apache.log4j.Logger;
10  import org.rpi.player.events.EventDurationUpdate;
11  import org.rpi.player.events.EventFinishedCurrentTrack;
12  import org.rpi.player.events.EventStatusChanged;
13  import org.rpi.player.events.EventTimeUpdate;
14  
15  public class OutputReader extends Thread {
16  
17  	private static Logger log = Logger.getLogger(OutputReader.class);
18  
19  	private static final Pattern END_PATTERN = Pattern.compile(".*\\x2e\\x2e\\x2e\\x20\\(.*\\x20.*\\).*");
20  
21  	private Process process = null;
22  	private MPlayer mPlayer = null;
23  
24  	private boolean readStopped;
25  
26  	private boolean bUpdate = true;
27  
28  	public OutputReader(MPlayer mPlayer) {
29  		this.setName("OR-" + mPlayer.getUniqueId());
30  		this.mPlayer = mPlayer;
31  		this.process = mPlayer.getProcess();
32  	}
33  
34  	private void read(String line) {
35  		boolean print = true;
36  		//log.debug(line);
37  		if (line.startsWith("Starting playback...")) {
38  			mPlayer.playingTrack();
39  		}
40  		
41  		else if(line.startsWith("Cache fill:"))
42  		{
43  			EventStatusChanged ev = new EventStatusChanged();
44  			ev.setStatus("Buffering");
45  			mPlayer.fireEvent(ev);
46  		}
47  
48  		else if (line.startsWith("ANS_LENGTH")) {
49  			String lengths[] = line.split("=");
50  			if (lengths.length > 1) {
51  				long l = stringToLong(lengths[1]);
52  				if (l != -99) {
53  					EventDurationUpdate e = new EventDurationUpdate();
54  					e.setDuration(l);
55  					mPlayer.fireEvent(e);
56  				}
57  				mPlayer.getTrackInfo().setDuration(l);
58  			}
59  			print = false;
60  		}
61  
62  		else if (line.contains("=====  PAUSE  =====")) {
63  			log.debug("Paused");
64  		}
65  
66  		else if (line.startsWith("ANS_TIME_POSITION")) {
67  			String lengths[] = line.split("=");
68  			if (lengths.length > 1) {
69  				EventTimeUpdate ev = new EventTimeUpdate();
70  				ev.setTime(stringToLong(lengths[1]));
71  				mPlayer.fireEvent(ev);
72  			}
73  			print = false;
74  		}
75  
76  		else if (line.startsWith("ANS_AUDIO_BITRATE")) {
77  			mPlayer.getTrackInfo().setBitrate(stringToLong(line));
78  			print = false;
79  		}
80  
81  		else if (line.startsWith("ANS_AUDIO_CODEC")) {
82  			String[] splits = line.split("=");
83  			if (splits.length == 2) {
84  				String codec = splits[1];
85  				codec = codec.replaceAll("[']", "");
86  				mPlayer.getTrackInfo().setCodec(codec);
87  			}
88  
89  			print = false;
90  		}
91  
92  		else if (line.startsWith("ANS_AUDIO_SAMPLES")) {
93  			String[] splits = line.split(",");
94  			if (splits.length == 2) {
95  				mPlayer.getTrackInfo().setSampleRate(stringToLong(splits[0]));
96  				print = false;
97  			}
98  		}
99  
100 		else if (line.startsWith("File not found")) {
101 			// Stop output reader
102 			readStopped = true;
103 			log.error("FILE NOT FOUND");
104 		}
105 
106 		else if (line.startsWith("Exiting... (Quit)")) {
107 			if (isUpdate()) {
108 				mPlayer.setStatus("Stopped");
109 			}
110 			EventFinishedCurrentTrack ev = new EventFinishedCurrentTrack();
111 			ev.setQuit(true);
112 			mPlayer.fireEvent(ev);
113 		}
114 
115 		// Get Track info for Radio Streams.
116 		else if (line.startsWith("ICY")) {
117 			log.debug("ICY INFO: " + line);
118 			print = false;
119 			try {
120 				String temp = line.substring(line.toUpperCase().indexOf("STREAMTITLE='") + 13);
121 				if (temp.length() > 0) {
122 					String[] splits = temp.split(";");
123 					if (splits.length > 1) {
124 						String[] fulls = splits[0].split("-");
125 						if (fulls.length >1) {
126 							String title = fulls[1].trim();
127 							String artist = fulls[0].trim();
128 							if (title.endsWith("'")) {
129 								title = title.substring(0, title.length() - 1);
130 							}
131 							//log.debug("ICY IFNO Artist is: " + artist + " Title is: " + title);
132 							mPlayer.updateInfo(artist, title);
133 						}
134 						else
135 						{
136 							//Just for Absolute radio who decided to use '~' as a seperator 
137 							String[] abs = splits[0].split("~");
138 							if(abs.length>1)
139 							{
140 								String artist = abs[0].trim();
141 								String title = abs[1].trim();
142 								if (artist.endsWith("'")) {
143 									artist = artist.substring(0, artist.length() - 1);
144 								}
145 								//log.debug("ICY IFNO Artist is: " + artist + " Title is: " + title);
146 								mPlayer.updateInfo(artist, title);
147 							}
148 						}
149 					}
150 				}
151 			} catch (Exception e) {
152 				log.error("Whoops, error handling ICY Info", e);
153 			}
154 		}
155 
156 		// End
157 		else if (END_PATTERN.matcher(line).matches() && !this.readStopped) {
158 			log.debug("Finished");
159 			mPlayer.stoppedPlaying();
160 		}
161 		
162 
163 		if (print) {
164 			if (!line.trim().equals("")) {
165 				log.debug(line);
166 			}
167 		}
168 
169 	}
170 
171 	/***
172 	 * Converts a String With decimal places to a long
173 	 * 
174 	 * @param s
175 	 * @return
176 	 */
177 	private long stringToLong(String s) {
178 		s = s.replaceAll("[^.0-9\\s]", "");
179 		NumberFormat nf = NumberFormat.getInstance();
180 		Number number;
181 		try {
182 			number = nf.parse(s);
183 			long l = number.longValue();
184 			return l;
185 		} catch (ParseException e) {
186 			e.printStackTrace();
187 		}
188 		return -99;
189 	}
190 
191 	@Override
192 	public void run() {
193 		String line = null;
194 		BufferedReader in = new BufferedReader(new InputStreamReader(this.process.getInputStream()));
195 		try {
196 			line = in.readLine();
197 			while (line != null && (mPlayer.isPlaying() || mPlayer.isLoading()) && !isInterrupted()) {
198 				read(line);
199 				line = in.readLine();
200 			}
201 		} catch (final IOException e) {
202 			log.error("Error OutputReader", e);
203 		} finally {
204 			log.debug("Closing BufferedReader");
205 			CloseMe.close(in);
206 			mPlayer.endPositionThread();
207 		}
208 	}
209 
210 	/**
211 	 * @return the bUpdate
212 	 */
213 	private boolean isUpdate() {
214 		return bUpdate;
215 	}
216 
217 	/**
218 	 * @param bUpdate the bUpdate to set
219 	 */
220 //	private void setUpdate(boolean bUpdate) {
221 //		this.bUpdate = bUpdate;
222 //	}
223 
224 }