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    public JMFInit(String[] args, boolean visible) {
047        super("Initializing JMF...");
048
049        this.visible = visible;
050
051        Registry.set("secure.allowCaptureFromApplets", true);
052        Registry.set("secure.allowSaveFileFromApplets", true);
053
054        updateTemp(args);
055
056        try {
057            Registry.commit();
058        }
059        catch (Exception e) {
060
061            LOGGER.fine("Failed to commit to JMFRegistry!");
062        }
063
064        Thread detectThread = new Thread(this);
065        detectThread.run();
066
067        /*
068           * int slept = 0; while (!done && slept < 60 * 1000 * 2) { try {
069           * Thread.currentThread().sleep(500); } catch (InterruptedException ie) { }
070           * slept += 500; }
071           *
072           * if (!done) { console.error("Detection is taking too long!
073           * Aborting!"); message("Detection is taking too long! Aborting!"); }
074           *
075           * try { Thread.currentThread().sleep(2000); } catch
076           * (InterruptedException ie) { }
077           */
078    }
079
080    @Override
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            LOGGER.fine("Setting cache directory to " + tempDir);
093            try {
094                Registry.set("secure.cacheDir", tempDir);
095                Registry.commit();
096
097                LOGGER.fine("Updated registry");
098            }
099            catch (Exception e) {
100                LOGGER.fine("Couldn't update registry!");
101            }
102        }
103    }
104
105    @SuppressWarnings("LiteralClassName")
106    private static void detectCaptureDevices() {
107        // check if JavaSound capture is available
108        LOGGER.fine("Looking for Audio capturer");
109        Class<?> dsauto;
110        try {
111            dsauto = Class.forName("DirectSoundAuto");
112            dsauto.getConstructor().newInstance();
113            LOGGER.fine("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.getConstructor().newInstance();
126            LOGGER.fine("Finished detecting javasound capturer");
127        }
128        catch (ThreadDeath td) {
129            throw td;
130        }
131        catch (Throwable t) {
132             LOGGER.fine("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 static 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.getConstructor().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                @SuppressWarnings("unchecked")
211                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
212                        plType);
213                int listSize = rendList.size();
214                if (rendList.elementAt(listSize - 1).equals(dar)) {
215                    rendList.removeElementAt(listSize - 1);
216                    rendList.insertElementAt(dar, 0);
217                    PlugInManager.setPlugInList(rendList, plType);
218                    PlugInManager.commit();
219                    // Log.debug("registered");
220                }
221                rend.close();
222            }
223            catch (Throwable t) {
224                // Log.debug("Error " + t);
225            }
226        }
227        catch (Throwable tt) {
228            // Do nothing.
229        }
230    }
231
232    private static void detectS8DirectAudio() {
233        Class<?> cls;
234        int plType = PlugInManager.RENDERER;
235        String dar = "com.sun.media.renderer.audio.DirectAudioRenderer";
236        try {
237            // Check if this is the solaris Performance Pack - hack
238            cls = Class.forName("SunVideoAuto");
239
240            // Find the renderer class and instantiate it.
241            cls = Class.forName(dar);
242
243            Renderer rend = (Renderer) cls.getConstructor().newInstance();
244
245            if (rend instanceof ExclusiveUse
246                    && !((ExclusiveUse) rend).isExclusive()) {
247                // sol8+, DAR supports mixing
248                @SuppressWarnings("unchecked")
249                Vector<String> rendList = PlugInManager.getPlugInList(null, null,
250                        plType);
251                int listSize = rendList.size();
252                boolean found = false;
253                String rname;
254
255                for (int i = 0; i < listSize; i++) {
256                    rname = rendList.elementAt(i);
257                    if (rname.equals(dar)) { // DAR is in the registry
258                        found = true;
259                        rendList.removeElementAt(i);
260                        break;
261                    }
262                }
263
264                if (found) {
265                    rendList.insertElementAt(dar, 0);
266                    PlugInManager.setPlugInList(rendList, plType);
267                    PlugInManager.commit();
268                }
269            }
270        }
271        catch (Throwable tt) {
272            // Do nothing.
273        }
274    }
275
276    public static void start(boolean visible) {
277        new JMFInit(null, visible);
278    }
279}