1 package org.daisy.pipeline.audio;
2
3 import java.io.InputStream;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.concurrent.CopyOnWriteArrayList;
9 import java.util.Map;
10 import java.util.Optional;
11
12 import javax.sound.sampled.AudioFileFormat;
13 import javax.sound.sampled.AudioInputStream;
14 import javax.sound.sampled.UnsupportedAudioFileException;
15
16 import org.osgi.service.component.annotations.Component;
17 import org.osgi.service.component.annotations.Reference;
18 import org.osgi.service.component.annotations.ReferenceCardinality;
19 import org.osgi.service.component.annotations.ReferencePolicy;
20
21 @Component(
22 name = "audio-services",
23 service = { AudioServices.class }
24 )
25 public class AudioServices {
26
27 public Optional<AudioEncoder> newEncoder(AudioFileFormat.Type fileType, Map<String,String> params) {
28 for (AudioEncoderService s : encoderServices) {
29 if (s.supportsFileType(fileType)) {
30 Optional<AudioEncoder> e = s.newEncoder(params);
31 if (e.isPresent())
32 return e;
33 }
34 }
35 return Optional.empty();
36 }
37
38
39
40
41 public Optional<AudioDecoder> newDecoder(Map<String,String> params) {
42 List<AudioDecoder> decoders = new ArrayList<>();
43 Iterator<AudioDecoderService> decoderServices = this.decoderServices.iterator();
44 return Optional.of(
45 new AudioDecoder() {
46 public AudioInputStream decode(InputStream input) throws UnsupportedAudioFileException, Throwable {
47 for (AudioDecoder d : decoders) {
48 try {
49 return d.decode(input);
50 } catch (UnsupportedAudioFileException e) {
51 }
52 }
53 while (decoderServices.hasNext()) {
54 Optional<AudioDecoder> d = decoderServices.next().newDecoder(params);
55 if (d.isPresent()) {
56 decoders.add(d.get());
57 try {
58 return d.get().decode(input);
59 } catch (UnsupportedAudioFileException e) {
60 }
61 }
62 }
63 throw new UnsupportedAudioFileException();
64 }
65 }
66 );
67 }
68
69 public Optional<AudioDecoder> newDecoder(AudioFileFormat.Type fileType, Map<String,String> params) {
70 for (AudioDecoderService s : decoderServices) {
71 if (s.supportsFileType(fileType)) {
72 Optional<AudioDecoder> d = s.newDecoder(params);
73 if (d.isPresent())
74 return d;
75 }
76 }
77 return Optional.empty();
78 }
79
80 private final Collection<AudioEncoderService> encoderServices = new CopyOnWriteArrayList<>();
81 private final Collection<AudioDecoderService> decoderServices = new CopyOnWriteArrayList<>();
82
83 @Reference(
84 name = "audio-encoder-service",
85 unbind = "-",
86 service = AudioEncoderService.class,
87 cardinality = ReferenceCardinality.MULTIPLE,
88 policy = ReferencePolicy.STATIC
89 )
90 public void addEncoderService(AudioEncoderService service) {
91 encoderServices.add(service);
92 }
93
94 public void removeEncoderService(AudioEncoderService service) {
95 encoderServices.remove(service);
96 }
97
98 @Reference(
99 name = "audio-decoder-service",
100 unbind = "-",
101 service = AudioDecoderService.class,
102 cardinality = ReferenceCardinality.MULTIPLE,
103 policy = ReferencePolicy.STATIC
104 )
105 public void addDecoderService(AudioDecoderService service) {
106 decoderServices.add(service);
107 }
108
109 public void removeDecoderService(AudioDecoderService service) {
110 decoderServices.remove(service);
111 }
112 }