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.jingleold.mediaimpl;
018
019import java.awt.Frame;
020import java.util.Vector;
021import java.util.logging.Logger;
022
023import javax.media.Format;
024import javax.media.PlugInManager;
025import javax.media.Renderer;
026import javax.media.format.AudioFormat;
027
028import com.sun.media.ExclusiveUse;
029import com.sun.media.util.Registry;
030
031@SuppressWarnings("UnusedVariable")
032public class JMFInit extends Frame implements Runnable {
033
034    private static final long serialVersionUID = 6476412003260641680L;
035
036    private static final Logger LOGGER = Logger.getLogger(JMFInit.class.getName());
037
038    private String tempDir = "/tmp";
039
040    private boolean done = false;
041
042    private String userHome;
043
044    private boolean visible = false;
045
046    @SuppressWarnings({"this-escape", "DoNotCall"})
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            LOGGER.fine("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    @Override
082    public void run() {
083        detectDirectAudio();
084        detectS8DirectAudio();
085        detectCaptureDevices();
086        done = true;
087    }
088
089    private void updateTemp(String[] args) {
090        if (args != null && args.length > 0) {
091            tempDir = args[0];
092
093            LOGGER.fine("Setting cache directory to " + tempDir);
094            try {
095                Registry.set("secure.cacheDir", tempDir);
096                Registry.commit();
097
098                LOGGER.fine("Updated registry");
099            }
100            catch (Exception e) {
101                LOGGER.fine("Couldn't update registry!");
102            }
103        }
104    }
105
106    @SuppressWarnings("LiteralClassName")
107    private static void detectCaptureDevices() {
108        // check if JavaSound capture is available
109        LOGGER.fine("Looking for Audio capturer");
110        Class<?> dsauto;
111        try {
112            dsauto = Class.forName("DirectSoundAuto");
113            dsauto.getConstructor().newInstance();
114            LOGGER.fine("Finished detecting DirectSound capturer");
115        }
116        catch (ThreadDeath td) {
117            throw td;
118        }
119        catch (Throwable t) {
120            // Do nothing.
121        }
122
123        Class<?> jsauto;
124        try {
125            jsauto = Class.forName("JavaSoundAuto");
126            jsauto.getConstructor().newInstance();
127            LOGGER.fine("Finished detecting javasound capturer");
128        }
129        catch (ThreadDeath td) {
130            throw td;
131        }
132        catch (Throwable t) {
133             LOGGER.fine("JavaSound capturer detection failed!");
134        }
135
136        /*
137        // Check if VFWAuto or SunVideoAuto is available
138        message("Looking for video capture devices");
139        Class auto = null;
140        Class autoPlus = null;
141        try {
142            auto = Class.forName("VFWAuto");
143        }
144        catch (Exception e) {
145        }
146        if (auto == null) {
147            try {
148                auto = Class.forName("SunVideoAuto");
149            }
150            catch (Exception ee) {
151
152            }
153            try {
154                autoPlus = Class.forName("SunVideoPlusAuto");
155            }
156            catch (Exception ee) {
157
158            }
159        }
160        if (auto == null) {
161            try {
162                auto = Class.forName("V4LAuto");
163            }
164            catch (Exception ee) {
165
166            }
167        }
168        try {
169            Object instance = auto.newInstance();
170            if (autoPlus != null) {
171                Object instancePlus = autoPlus.newInstance();
172            }
173
174            message("Finished detecting video capture devices");
175        }
176        catch (ThreadDeath td) {
177            throw td;
178        }
179        catch (Throwable t) {
180
181            message("Capture device detection failed!");
182        }
183        */
184    }
185
186    private static void detectDirectAudio() {
187        Class<?> cls;
188        int plType = PlugInManager.RENDERER;
189        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
190        try {
191            // Check if this is the Windows Performance Pack - hack
192            cls = Class.forName("VFWAuto");
193            // Check if DS capture is supported, otherwise fail DS renderer
194            // since NT doesn't have capture
195            cls = Class.forName("com.sun.media.protocol.dsound.DSound");
196            // Find the renderer class and instantiate it.
197            cls = Class.forName(dar);
198
199            Renderer rend = (Renderer) cls.getConstructor().newInstance();
200            try {
201                // Set the format and open the device
202                AudioFormat af = new AudioFormat(AudioFormat.LINEAR, 44100, 16,
203                        2);
204                rend.setInputFormat(af);
205                rend.open();
206                Format[] inputFormats = rend.getSupportedInputFormats();
207                // Register the device
208                PlugInManager.addPlugIn(dar, inputFormats, new Format[0],
209                        plType);
210                // Move it to the top of the list
211                @SuppressWarnings("unchecked")
212                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
213                        plType);
214                int listSize = rendList.size();
215                if (rendList.elementAt(listSize - 1).equals(dar)) {
216                    rendList.removeElementAt(listSize - 1);
217                    rendList.insertElementAt(dar, 0);
218                    PlugInManager.setPlugInList(rendList, plType);
219                    PlugInManager.commit();
220                    // Log.debug("registered");
221                }
222                rend.close();
223            }
224            catch (Throwable t) {
225                // Log.debug("Error " + t);
226            }
227        }
228        catch (Throwable tt) {
229            // Do nothing.
230        }
231    }
232
233    private static void detectS8DirectAudio() {
234        Class<?> cls;
235        int plType = PlugInManager.RENDERER;
236        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
237        try {
238            // Check if this is the solaris Performance Pack - hack
239            cls = Class.forName("SunVideoAuto");
240
241            // Find the renderer class and instantiate it.
242            cls = Class.forName(dar);
243
244            Renderer rend = (Renderer) cls.getConstructor().newInstance();
245
246            if (rend instanceof ExclusiveUse
247                    && !((ExclusiveUse) rend).isExclusive()) {
248                // sol8+, DAR supports mixing
249                @SuppressWarnings("unchecked")
250                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
251                        plType);
252                int listSize = rendList.size();
253                boolean found = false;
254                String rname;
255
256                for (int i = 0; i < listSize; i++) {
257                    rname = rendList.elementAt(i);
258                    if (rname.equals(dar)) { // DAR is in the registry
259                        found = true;
260                        rendList.removeElementAt(i);
261                        break;
262                    }
263                }
264
265                if (found) {
266                    rendList.insertElementAt(dar, 0);
267                    PlugInManager.setPlugInList(rendList, plType);
268                    PlugInManager.commit();
269                }
270            }
271        }
272        catch (Throwable tt) {
273            // Do nothing.
274        }
275    }
276
277    public static void start(boolean visible) {
278        new JMFInit(null, visible);
279    }
280}