View Javadoc

1   /***
2    *     Ambient - A music player for the Android platform
3    Copyright (C) 2007 Martin Vysny
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  
19  package sk.baka.ambient.commons;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  
24  /***
25   * Counts bytes which are being read.
26   * 
27   * @author Martin Vysny
28   */
29  public abstract class CountingInputStream extends InputStream {
30  	@Override
31  	public int read() throws IOException {
32  		final int result = in.read();
33  		if (result >= 0) {
34  			currentPosition++;
35  			checkPos();
36  		}
37  		return result;
38  	}
39  
40  	private void checkPos() {
41  		if (currentPosition >= nextEventPosition) {
42  			nextEventPosition += blockLength;
43  			countEvent(currentPosition);
44  		}
45  	}
46  
47  	@Override
48  	public int read(byte[] buffer, int offset, int count) throws IOException {
49  		final int result = in.read(buffer, offset, count);
50  		if (result > 0) {
51  			currentPosition += result;
52  			checkPos();
53  		}
54  		return result;
55  	}
56  
57  	@Override
58  	public int read(byte[] buffer) throws IOException {
59  		final int result = in.read(buffer);
60  		if (result > 0) {
61  			currentPosition += result;
62  			checkPos();
63  		}
64  		return result;
65  	}
66  
67  	@Override
68  	public long skip(long count) throws IOException {
69  		final long result = in.skip(count);
70  		currentPosition += result;
71  		checkPos();
72  		return result;
73  	}
74  
75  	@Override
76  	public synchronized void mark(int readlimit) {
77  		in.mark(readlimit);
78  		markedPosition = currentPosition;
79  	}
80  
81  	private long markedPosition = 0;
82  
83  	@Override
84  	public synchronized void reset() throws IOException {
85  		in.reset();
86  		if (!markSupported()) {
87  			currentPosition = 0;
88  		} else {
89  			currentPosition = markedPosition;
90  		}
91  	}
92  
93  	/***
94  	 * Fire events only when a block of given size (in bytes) has been read.
95  	 * This prevents firing events after each byte read.
96  	 */
97  	public final int blockLength;
98  	private final InputStream in;
99  
100 	/***
101 	 * Creates new counting stream instance.
102 	 * 
103 	 * @param in
104 	 *            poll this stream.
105 	 * @param blockLength
106 	 *            Fire events only when a block of given size (in bytes) has
107 	 *            been read. This prevents firing events after each byte read.
108 	 */
109 	public CountingInputStream(final InputStream in, final int blockLength) {
110 		super();
111 		this.in = in;
112 		this.blockLength = blockLength;
113 		nextEventPosition = blockLength;
114 	}
115 
116 	private long currentPosition = 0;
117 
118 	/***
119 	 * Returns number of bytes already read.
120 	 * 
121 	 * @return the number of bytes.
122 	 */
123 	public long getCurrentPosition() {
124 		return currentPosition;
125 	}
126 
127 	private long nextEventPosition;
128 
129 	/***
130 	 * Invoked when the position
131 	 * 
132 	 * @param currentPosition
133 	 */
134 	protected abstract void countEvent(final long currentPosition);
135 
136 	@Override
137 	public int available() throws IOException {
138 		return in.available();
139 	}
140 
141 	@Override
142 	public void close() throws IOException {
143 		in.close();
144 	}
145 
146 	@Override
147 	public boolean markSupported() {
148 		return in.markSupported();
149 	}
150 }