OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [javax/] [sound/] [sampled/] [gstreamer/] [lines/] [GstPipeline.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* GstPipeline.java -- Represents a Gstreamer Pipeline.
2
 Copyright (C) 2007 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package gnu.javax.sound.sampled.gstreamer.lines;
39
 
40
import java.io.FileOutputStream;
41
import java.io.IOException;
42
import java.util.prefs.Preferences;
43
 
44
import javax.sound.sampled.LineUnavailableException;
45
 
46
import gnu.classpath.Pointer;
47
 
48
/**
49
 * This class represent a GStreamer pipeline and is resposible to handle the
50
 * flow of data to and from the GStreamer native backend.
51
 *
52
 * @author Mario Torre <neugens@limasoftware.net>
53
 */
54
public class GstPipeline
55
{
56
  /*
57
   * Implementation note:
58
   * This class is at first a bit confusing as it serves as a gateway
59
   * to a real filesystem named pipe.
60
   * The pipelines is shared by the gstreamer backend and by the java code.
61
   * If the operation we are performing is to play a given stream of bytes,
62
   * we need to open the java side of the pipeline for writing, which is done
63
   * in the prepareWrite method. At the same time, the native side of the code
64
   * need to open the pipeline in read mode, to get access to the data,
65
   * and hence, act as a source element. This is why you will see terms
66
   * like "read" or "source" in methods that are used to write in the pipeline,
67
   * in other words, each the native operation is the opposite of the java
68
   * side operation.
69
   * Opening the pipe to record audio data from the sound card works the same
70
   * except that all the operation are inverted.
71
   */
72
 
73
  // These enums are used in the native code also, changes here must reflect
74
  // changes in the native code.
75
  public static enum State
76
  {
77
    PLAY, PAUSE, STOP, CLOSE
78
  }
79
 
80
  private static final int READ = 0;
81
  private static final int WRITE = 1;
82
  private static final int QUEUED = 1;
83
 
84
  private static final String CAPACITY_KEY = "Capacity";
85
 
86
  private static final Object [] lock = new Object[0];
87
 
88
  /*
89
   * Preference subsystem. We use this to store some system specific settings.
90
   */
91
  protected Preferences prefs =
92
    Preferences.userNodeForPackage(GstPipeline.class).node("GStreamer");
93
 
94
  // used by the native code, stores the size of the named pipeline
95
  // created by the operating system.
96
  private long capacity = -1;
97
 
98
  /** Represents the playing state of this Line. */
99
  private State state = State.STOP;
100
 
101
  /** The name of the named pipe. */
102
  // Will be setup and filled in the native code. See the native library
103
  // for details.
104
  private String name = null;
105
 
106
  /** This is the named pipe that will be read by the gstreamer backend. */
107
  private FileOutputStream output = null;
108
 
109
  /**
110
   * Defines if we are getting data from a sink pipe
111
   * or writing to a source pipe.
112
   */
113
  private boolean source = true;
114
 
115
  /** Indicate that we are ready to process audio data to/from the pipe. */
116
  private boolean ready = false;
117
 
118
  /**
119
   * This is the native GStreamer Pipeline.
120
   */
121
  // This field is used by the native code, so any change to it must be
122
  // followed by similar changes in the native peer.
123
  private Pointer pipeline = null;
124
 
125
  /**
126
   * Creates a new GstPipeline with a capacity of
127
   * {@link GstDataLine#DEFAULT_BUFFER_SIZE}.
128
   *
129
   * @see GstDataLine#DEFAULT_BUFFER_SIZE
130
   */
131
  public GstPipeline()
132
  {
133
    this(GstDataLine.DEFAULT_BUFFER_SIZE);
134
  }
135
 
136
  /**
137
   * Creates a new GstPipeline with a capacity of bufferSize.
138
   * @see GstDataLine#DEFAULT_BUFFER_SIZE
139
   */
140
  public GstPipeline(int bufferSize)
141
  {
142
    // see if we need to detect the size of the named pipe or we can use
143
    // an already computet default for this system.
144
    // Note that this is very different from the bufferSize parameter,
145
    // see below.
146
    capacity = prefs.getLong(CAPACITY_KEY, -1);
147
    if (capacity == -1)
148
      {
149
        synchronized (lock)
150
          {
151
            capacity = detect_pipe_size();
152
          }
153
 
154
        prefs.putLong(CAPACITY_KEY, capacity);
155
      }
156
 
157
    // FIXME: bufferSize actually not used nor needed by the backend.
158
    // Applications that expects a buffer of different size will be a
159
    // bit disappointed by that..
160
    init_instance();
161
 
162
    // need to remove the named pipe in case of abnormal termination
163
    Runtime.getRuntime().addShutdownHook(new CleanPipeline());
164
  }
165
 
166
  /**
167
   * Creates a source pipeline. A source pipeline is a pipe you send data for
168
   * processing using the write method.
169
   */
170
  public void createForWrite() throws LineUnavailableException
171
  {
172
    // create the named pipe
173
    if (!create_named_pipe(this.pipeline))
174
      throw new LineUnavailableException("Unable to create filesystem pipe");
175
 
176
    open_native_pipe(this.pipeline, READ);
177
    prepareWrite();
178
 
179
    this.source = true;
180
  }
181
 
182
  /**
183
   * @return the state
184
   */
185
  public State getState()
186
  {
187
    return this.state;
188
  }
189
 
190
  /**
191
   * Closes this pipeline.
192
   * Short hand for #setState(State.STOP).
193
   */
194
  public void close()
195
  {
196
    setState(State.STOP);
197
  }
198
 
199
  /**
200
   * @param state the state to set
201
   */
202
  public void setState(final State state)
203
  {
204
    int _state = -1;
205
    switch (state)
206
      {
207
        case PLAY:
208
          _state = 0;
209
          break;
210
 
211
        case PAUSE:
212
          _state = 1;
213
          break;
214
 
215
        case STOP: case CLOSE:
216
          _state = 2;
217
          closePipe();
218
          break;
219
      }
220
 
221
    if (set_state(pipeline, _state))
222
      GstPipeline.this.state = state;
223
  }
224
 
225
  /**
226
   * Return a reference to the GstPipeline native class as a Pointer object.
227
   * This method is intended as an helper accessor and the returned pointer
228
   * needs to be casted and used in the native code only.
229
   *
230
   * @return Pointer to the native GstPipeline class.
231
   */
232
  public Pointer getNativeClass()
233
  {
234
    return this.pipeline;
235
  }
236
 
237
  /**
238
   * Write length bytes from the given buffer into this pipeline,
239
   * starting at offset.
240
   * This method block if the pipeline can't accept more data.
241
   *
242
   * @param buffer
243
   * @param offset
244
   * @param length
245
   * @return
246
   */
247
  public int write(byte[] buffer, int offset, int length)
248
  {
249
    if (this.state == State.STOP)
250
      return -1;
251
    else if (this.state == State.PAUSE)
252
      return 0;
253
    else if (!ready)
254
      return -1;
255
 
256
    try
257
      {
258
        if (output != null)
259
          {
260
            output.write(buffer, offset, length);
261
            return length;
262
          }
263
        return 0;
264
      }
265
    catch (Exception e)
266
      {
267
        /* nothing to do */
268
      }
269
 
270
    return -1;
271
  }
272
 
273
  public int read(byte[] buffer, int offset, int length)
274
  {
275
    return 0;
276
  }
277
 
278
  public int available()
279
  {
280
    if (this.source)
281
      return available(this.pipeline, READ);
282
    else
283
      return available(this.pipeline, WRITE);
284
  }
285
 
286
  /**
287
   * Wait for remaining data to be enqueued in the pipeline.
288
   */
289
  public void drain()
290
  {
291
    if (this.state == State.STOP)
292
      return;
293
 
294
    try
295
      {
296
        // wait untill there is anymore data in the pipe
297
        while (available(this.pipeline, QUEUED) > 0)
298
          Thread.sleep(3000);
299
 
300
        // plus a bit to allow data to be processed
301
        Thread.sleep(1000);
302
      }
303
    catch (InterruptedException e)
304
      {
305
        /* nothing to do*/
306
      }
307
  }
308
 
309
  /**
310
   * Flush all the data currently waiting to be processed.
311
   */
312
  public void flush()
313
  {
314
    try
315
      {
316
        if (source)
317
          this.output.flush();
318
      }
319
    catch (IOException e)
320
      {
321
        /* nothing */
322
      }
323
  }
324
 
325
  private void closePipe()
326
  {
327
    try
328
      {
329
        GstPipeline.this.flush();
330
        if (source)
331
          GstPipeline.this.output.close();
332
      }
333
    catch (IOException e)
334
      {
335
        /* nothing to do */
336
      }
337
  }
338
 
339
  private void prepareWrite()
340
  {
341
    try
342
      {
343
        // if this is not completed for some reason, we will catch
344
        // in the write method. As this call can block, we assume we will
345
        // succeed and that the dataline can get data.
346
        GstPipeline.this.ready = true;
347
        GstPipeline.this.output = new FileOutputStream(name);
348
      }
349
    catch (Exception e)
350
      {
351
        GstPipeline.this.ready = false;
352
      }
353
  }
354
 
355
  /* ***** native ***** */
356
 
357
  /**
358
   * Initialize the native peer and enables the object cache.
359
   * It is meant to be used by the static initializer.
360
   */
361
  native private static final void init_id_cache();
362
 
363
  /**
364
   * Set the playing state of this pipeline.
365
   */
366
  native private static final boolean set_state(Pointer pipeline, int state);
367
 
368
  /**
369
   * Get the number of bytes currently available for reading or writing
370
   * from the pipeline.
371
   */
372
  native private static final int available(Pointer pipeline, int mode);
373
 
374
  /**
375
   * Open the native pipeline with the given mode.
376
   */
377
  native private static final void open_native_pipe(Pointer jpipeline,
378
                                                    int mode);
379
 
380
  /**
381
   * Close the native pipeline.
382
   */
383
  native private static final void close_native_pipe(Pointer jpipeline);
384
 
385
  /**
386
   * Initialize the native peer and enables the object cache.
387
   * It is meant to be used by the class constructor.
388
   */
389
  native private final void init_instance();
390
 
391
  /**
392
   * Crates the named pipe used to pass data between the application code
393
   * and gstreamer.
394
   */
395
  native private final boolean create_named_pipe(Pointer jpipeline);
396
 
397
  /**
398
   * Detect and return the size of the filesystem named pipe.
399
   */
400
  native private final long detect_pipe_size();
401
 
402
  private class CleanPipeline extends Thread
403
  {
404
    public void run()
405
    {
406
      GstPipeline.close_native_pipe(GstPipeline.this.pipeline);
407
    }
408
  }
409
 
410
  static
411
  {
412
    System.loadLibrary("gstreamerpeer"); //$NON-NLS-1$
413
    init_id_cache();
414
  }
415
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.