1   package org.daisy.pipeline.tts.calabash.impl;
2   
3   import java.util.concurrent.Semaphore;
4   import java.util.Map;
5   
6   import org.daisy.common.properties.Properties;
7   import org.daisy.common.properties.Properties.Property;
8   import org.daisy.common.xproc.calabash.XProcStep;
9   import org.daisy.common.xproc.calabash.XProcStepProvider;
10  import org.daisy.common.xproc.XProcMonitor;
11  import org.daisy.pipeline.audio.AudioServices;
12  import org.daisy.pipeline.tts.AudioFootprintMonitor;
13  import org.daisy.pipeline.tts.TTSRegistry;
14  
15  import com.xmlcalabash.core.XProcRuntime;
16  import com.xmlcalabash.runtime.XAtomicStep;
17  
18  import org.osgi.service.component.annotations.Component;
19  import org.osgi.service.component.annotations.Reference;
20  import org.osgi.service.component.annotations.ReferenceCardinality;
21  import org.osgi.service.component.annotations.ReferencePolicy;
22  
23  @Component(
24  	name = "ssml-to-audio",
25  	service = { XProcStepProvider.class },
26  	property = { "type:String={http://www.daisy.org/ns/pipeline/xproc}ssml-to-audio" }
27  )
28  public class SynthesizeProvider implements XProcStepProvider {
29  	private TTSRegistry mRegistry;
30  	private AudioServices mAudioServices;
31  	private Semaphore mStartSemaphore; //counter to limit the number of simultaneous text-to-speech steps
32  	private AudioFootprintMonitor mAudioFootprintMonitor;
33  
34  	static final Property ENABLE_LOG = Properties.getProperty("org.daisy.pipeline.tts.log",
35  	                                                          true,
36  	                                                          "Whether or not to make the TTS log available",
37  	                                                          false,
38  	                                                          "false");
39  
40  	@Override
41  	public XProcStep newStep(XProcRuntime runtime, XAtomicStep step, XProcMonitor monitor, Map<String,String> properties) {
42  		if (mStartSemaphore == null) {
43  			mStartSemaphore = new Semaphore(3, true);
44  		}
45  
46  		if (mAudioFootprintMonitor == null) {
47  			mAudioFootprintMonitor = new AudioFootprintMonitor();
48  		}
49  
50  		boolean error = false;
51  		if (mRegistry == null) {
52  			runtime.error(new RuntimeException("Registry of TTS engines is missing."));
53  			error = true;
54  		}
55  
56  		if (mAudioServices == null) {
57  			runtime.error(new RuntimeException("Registry of audio encoders is missing."));
58  			error = true;
59  		}
60  
61  		if (error)
62  			return null;
63  
64  		//warning: a reference is kept on the audio encoder during all the synthesizing process,
65  		//even if it is unregistered.
66  
67  		return new SynthesizeStep(runtime, step, mRegistry, mAudioServices, mStartSemaphore,
68  		                          mAudioFootprintMonitor, properties);
69  	}
70  
71  	@Reference(
72  		name = "TTSRegistry",
73  		unbind = "-",
74  		service = TTSRegistry.class,
75  		cardinality = ReferenceCardinality.MANDATORY,
76  		policy = ReferencePolicy.STATIC
77  	)
78  	protected void setTTSRegistry(TTSRegistry registry) {
79  		mRegistry = registry;
80  	}
81  
82  	protected void unsetTTSRegistry(TTSRegistry registry) {
83  		mRegistry = null;
84  	}
85  
86  	@Reference(
87  		name = "AudioServices",
88  		unbind = "-",
89  		service = AudioServices.class,
90  		cardinality = ReferenceCardinality.OPTIONAL,
91  		policy = ReferencePolicy.STATIC
92  	)
93  	protected void setAudioServices(AudioServices audioServices) {
94  		mAudioServices = audioServices;
95  	}
96  
97  	protected void unsetAudioServices(AudioServices audioServices) {
98  		mAudioServices = null;
99  	}
100 }