001/**
002 *
003 * Copyright the original author or authors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.jingle.mediaimpl;
018
019import java.awt.Frame;
020import java.awt.TextArea;
021import java.awt.Toolkit;
022import java.util.Vector;
023import java.util.logging.Logger;
024
025import javax.media.Format;
026import javax.media.PlugInManager;
027import javax.media.Renderer;
028import javax.media.format.AudioFormat;
029
030import com.sun.media.ExclusiveUse;
031import com.sun.media.util.Registry;
032
033public class JMFInit extends Frame implements Runnable {
034
035        private static final long serialVersionUID = 6476412003260641680L;
036
037        private static final Logger LOGGER = Logger.getLogger(JMFInit.class.getName());
038
039        private String tempDir = "/tmp";
040
041    private boolean done = false;
042
043    private String userHome;
044
045    private boolean visible = false;
046
047    public JMFInit(String[] args, boolean visible) {
048        super("Initializing JMF...");
049
050        this.visible = visible;
051
052        Registry.set("secure.allowCaptureFromApplets", true);
053        Registry.set("secure.allowSaveFileFromApplets", true);
054
055        updateTemp(args);
056
057        try {
058            Registry.commit();
059        }
060        catch (Exception e) {
061
062            message("Failed to commit to JMFRegistry!");
063        }
064
065        Thread detectThread = new Thread(this);
066        detectThread.run();
067
068        /*
069           * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {
070           * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }
071           * slept += 500; }
072           *
073           * if (!done) { console.error("Detection is taking too long!
074           * Aborting!"); message("Detection is taking too long! Aborting!"); }
075           *
076           * try { Thread.currentThread().sleep(2000); } catch
077           * (InterruptedException ie) { }
078           */
079    }
080
081    public void run() {
082        detectDirectAudio();
083        detectS8DirectAudio();
084        detectCaptureDevices();
085        done = true;
086    }
087
088    private void updateTemp(String[] args) {
089        if (args != null && args.length > 0) {
090            tempDir = args[0];
091
092            message("Setting cache directory to " + tempDir);
093            Registry r = new Registry();
094            try {
095                r.set("secure.cacheDir", tempDir);
096                r.commit();
097
098                message("Updated registry");
099            }
100            catch (Exception e) {
101                message("Couldn't update registry!");
102            }
103        }
104    }
105
106    private void detectCaptureDevices() {
107        // check if JavaSound capture is available
108        message("Looking for Audio capturer");
109        Class<?> dsauto;
110        try {
111            dsauto = Class.forName("DirectSoundAuto");
112            dsauto.newInstance();
113            message("Finished detecting DirectSound capturer");
114        }
115        catch (ThreadDeath td) {
116            throw td;
117        }
118        catch (Throwable t) {
119            //Do nothing
120        }
121
122        Class<?> jsauto;
123        try {
124            jsauto = Class.forName("JavaSoundAuto");
125            jsauto.newInstance();
126            message("Finished detecting javasound capturer");
127        }
128        catch (ThreadDeath td) {
129            throw td;
130        }
131        catch (Throwable t) {
132            message("JavaSound capturer detection failed!");
133        }
134
135        /*
136        // Check if VFWAuto or SunVideoAuto is available
137        message("Looking for video capture devices");
138        Class auto = null;
139        Class autoPlus = null;
140        try {
141            auto = Class.forName("VFWAuto");
142        }
143        catch (Exception e) {
144        }
145        if (auto == null) {
146            try {
147                auto = Class.forName("SunVideoAuto");
148            }
149            catch (Exception ee) {
150
151            }
152            try {
153                autoPlus = Class.forName("SunVideoPlusAuto");
154            }
155            catch (Exception ee) {
156
157            }
158        }
159        if (auto == null) {
160            try {
161                auto = Class.forName("V4LAuto");
162            }
163            catch (Exception ee) {
164
165            }
166        }
167        try {
168            Object instance = auto.newInstance();
169            if (autoPlus != null) {
170                Object instancePlus = autoPlus.newInstance();
171            }
172
173            message("Finished detecting video capture devices");
174        }
175        catch (ThreadDeath td) {
176            throw td;
177        }
178        catch (Throwable t) {
179
180            message("Capture device detection failed!");
181        }
182        */
183    }
184
185    private void detectDirectAudio() {
186        Class<?> cls;
187        int plType = PlugInManager.RENDERER;
188        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
189        try {
190            // Check if this is the Windows Performance Pack - hack
191            cls = Class.forName("VFWAuto");
192            // Check if DS capture is supported, otherwise fail DS renderer
193            // since NT doesn't have capture
194            cls = Class.forName("com.sun.media.protocol.dsound.DSound");
195            // Find the renderer class and instantiate it.
196            cls = Class.forName(dar);
197
198            Renderer rend = (Renderer) cls.newInstance();
199            try {
200                // Set the format and open the device
201                AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,
202                        2);
203                rend.setInputFormat(af);
204                rend.open();
205                Format[] inputFormats = rend.getSupportedInputFormats();
206                // Register the device
207                PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
208                        plType);
209                // Move it to the top of the list
210                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
211                        plType);
212                int listSize = rendList.size();
213                if (rendList.elementAt(listSize - 1).equals(dar)) {
214                    rendList.removeElementAt(listSize - 1);
215                    rendList.insertElementAt(dar, 0);
216                    PlugInManager.setPlugInList(rendList, plType);
217                    PlugInManager.commit();
218                    // Log.debug("registered");
219                }
220                rend.close();
221            }
222            catch (Throwable t) {
223                // Log.debug("Error " + t);
224            }
225        }
226        catch (Throwable tt) {
227            //Do nothing
228        }
229    }
230
231    private void detectS8DirectAudio() {
232        Class<?> cls;
233        int plType = PlugInManager.RENDERER;
234        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
235        try {
236            // Check if this is the solaris Performance Pack - hack
237            cls = Class.forName("SunVideoAuto");
238
239            // Find the renderer class and instantiate it.
240            cls = Class.forName(dar);
241
242            Renderer rend = (Renderer) cls.newInstance();
243
244            if (rend instanceof ExclusiveUse
245                    && !((ExclusiveUse) rend).isExclusive()) {
246                // sol8+, DAR supports mixing
247                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
248                        plType);
249                int listSize = rendList.size();
250                boolean found = false;
251                String rname = null;
252
253                for (int i = 0; i < listSize; i++) {
254                    rname = (String) (rendList.elementAt(i));
255                    if (rname.equals(dar)) { // DAR is in the registry
256                        found = true;
257                        rendList.removeElementAt(i);
258                        break;
259                    }
260                }
261
262                if (found) {
263                    rendList.insertElementAt(dar, 0);
264                    PlugInManager.setPlugInList(rendList, plType);
265                    PlugInManager.commit();
266                }
267            }
268        }
269        catch (Throwable tt) {
270            //Do nothing
271        }
272    }
273
274    private void message(String mesg) {
275        LOGGER.fine(mesg);
276    }
277
278    private void createGUI() {
279        TextArea textBox = new TextArea(5, 50);
280        add("Center", textBox);
281        textBox.setEditable(false);
282        addNotify();
283        pack();
284
285        int scrWidth = (int) Toolkit.getDefaultToolkit().getScreenSize()
286                .getWidth();
287        int scrHeight = (int) Toolkit.getDefaultToolkit().getScreenSize()
288                .getHeight();
289
290        setLocation((scrWidth - getWidth()) / 2, (scrHeight - getHeight()) / 2);
291
292        setVisible(visible);
293
294    }
295
296    public static void start(boolean visible) {
297        new JMFInit(null, visible);
298    }
299}