View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.captcha.modules.jcaptcha.service.sound;
35  
36  import java.io.ByteArrayInputStream;
37  import java.io.IOException;
38  import java.util.ArrayList;
39  import java.util.Collection;
40  import java.util.Iterator;
41  import java.util.List;
42  
43  import javax.sound.sampled.AudioFormat;
44  import javax.sound.sampled.AudioInputStream;
45  import javax.sound.sampled.AudioSystem;
46  
47  
48  /**
49   *
50   * @author lutecer
51   *
52   */
53  public class SequenceAudioInputStream extends AudioInputStream
54  {
55      private List<AudioInputStream> _audioInputStreamList;
56      private int _nCurrentStream;
57  
58      /**
59       *
60       * @param audioFormat the audio Format
61       * @param audioInputStreams the audio InputStreams
62       */
63      public SequenceAudioInputStream( AudioFormat audioFormat, Collection<AudioInputStream> audioInputStreams )
64      {
65          super( new ByteArrayInputStream( new byte[0] ), audioFormat, AudioSystem.NOT_SPECIFIED );
66          _audioInputStreamList = new ArrayList<AudioInputStream>( audioInputStreams );
67          _nCurrentStream = 0;
68      }
69  
70      /**
71       *
72       * @return the audio inputStream
73       */
74      private AudioInputStream getCurrentStream(  )
75      {
76          return _audioInputStreamList.get( _nCurrentStream );
77      }
78  
79      /**
80       *
81       * @return true if mcurrent stream < audioInputStreamList size
82       */
83      private boolean advanceStream(  )
84      {
85          _nCurrentStream++;
86  
87          boolean bAnotherStreamAvailable = ( _nCurrentStream < _audioInputStreamList.size(  ) );
88  
89          return bAnotherStreamAvailable;
90      }
91  
92      /**
93       * @return frame length
94       */
95      public long getFrameLength(  )
96      {
97          long lLengthInFrames = 0;
98          Iterator<AudioInputStream> streamIterator = _audioInputStreamList.iterator(  );
99  
100         while ( streamIterator.hasNext(  ) )
101         {
102             AudioInputStream stream = streamIterator.next( );
103             long lLength = stream.getFrameLength(  );
104 
105             if ( lLength == AudioSystem.NOT_SPECIFIED )
106             {
107                 return AudioSystem.NOT_SPECIFIED;
108             }
109             else
110             {
111                 lLengthInFrames += lLength;
112             }
113         }
114 
115         return lLengthInFrames;
116     }
117 
118     /**
119      *  @return the byte read
120      *  @throws IOException the IOException
121      */
122     public int read(  ) throws IOException
123     {
124         AudioInputStream stream = getCurrentStream(  );
125         int nByte = stream.read(  );
126 
127         if ( nByte == -1 )
128         {
129             /*
130              * The end of the current stream has been signaled. We try to
131              * advance to the next stream.
132              */
133             boolean bAnotherStreamAvailable = advanceStream(  );
134 
135             if ( bAnotherStreamAvailable )
136             {
137                 /*
138                  * There is another stream. We recurse into this method to read
139                  * from it.
140                  */
141                 return read(  );
142             }
143             else
144             {
145                 /*
146                  * No more data. We signal EOF.
147                  */
148                 return -1;
149             }
150         }
151         else
152         {
153             /*
154              * The most common case: We return the byte.
155              */
156             return nByte;
157         }
158     }
159 
160     /**
161      * @param abData the data
162      * @param nOffset the offset
163      * @param nLength the length
164      * @return the bytes read
165      * @throws IOException the IOException
166      */
167     public int read( byte[] abData, int nOffset, int nLength )
168         throws IOException
169     {
170         AudioInputStream stream = getCurrentStream(  );
171         int nBytesRead = stream.read( abData, nOffset, nLength );
172 
173         if ( nBytesRead == -1 )
174         {
175             /*
176              * The end of the current stream has been signaled. We try to
177              * advance to the next stream.
178              */
179             boolean bAnotherStreamAvailable = advanceStream(  );
180 
181             if ( bAnotherStreamAvailable )
182             {
183                 /*
184                  * There is another stream. We recurse into this method to read
185                  * from it.
186                  */
187                 return read( abData, nOffset, nLength );
188             }
189             else
190             {
191                 /*
192                  * No more data. We signal EOF.
193                  */
194                 return -1;
195             }
196         }
197         else
198         {
199             /*
200              * The most common case: We return the length.
201              */
202             return nBytesRead;
203         }
204     }
205 
206     /**
207      * @return the current stream available
208      * @throws IOException the IOException
209      */
210     public int available(  ) throws IOException
211     {
212         return getCurrentStream(  ).available(  );
213     }
214 }
215 /** * SequenceAudioInputStream.java ** */