/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright 2014, OpenSpace Solutions LLC. All Right Reserved.
*/
package com.chiorichan.dvr.registry;
import com.chiorichan.Loader;
import com.chiorichan.dvr.VideoWriter;
import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamDiscoveryEvent;
import com.github.sarxos.webcam.WebcamDiscoveryListener;
import com.github.sarxos.webcam.WebcamException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class InputRegistry implements WebcamDiscoveryListener
{
protected static List<VideoInput> inputs = new CopyOnWriteArrayList<VideoInput>();
protected static InputRegistry instance;
public static void destroyAllDevices()
{
List<VideoWriter> writers = VideoInput.getVideoWriters();
if ( writers.size() > 0 )
{
for ( VideoWriter w : writers )
{
// VideoWriters might shutdown early if they manually check the isRunning boolean in DVRLoader.
// But since it's important that VideoWriters are closed before we close the VideoInput, we notify it and wait.
w.detachedFromInput = true;
Loader.getLogger().info( "Notified thread `" + w.currentThread.getName() + "` of the shutdown! WAITING." );
}
boolean allFinished = false;
long looperCount = 0;
Boolean g = false;
// Wait for all VideoWriters to finish their operation.
// TODO: Monitor if any VideoWriters don't shutdown like they should, TERMINATE THEM!
// Copied this way of doing things from the main Server Thread loop.
for ( long j = 0L; !allFinished; g = true )
{
try
{
int state = 0;
for ( VideoWriter w : writers )
{
if ( !w.isRunning )
if ( state != 2 )
state = 1;
else
state = 2;
}
if ( state == 1 )
allFinished = true;
looperCount++;
// 10 Seconds
if ( looperCount > 15000 )
for ( VideoWriter w : writers )
{
// Is there a better way to do this?
if ( w.currentThread != null && w.isRunning )
w.currentThread.interrupt();
}
Thread.sleep( 100L );
}
catch ( Exception ex )
{
Loader.getLogger().severe( "Exception Thrown in VideoInput Shutdown: " + ex.getMessage() );
allFinished = true;
break;
}
}
}
for ( VideoInput i : inputs )
{
i.close();
}
writers = null;
inputs.clear();
Loader.getLogger().info( "All VideoWriters and VideoInputs closed!" );
}
public static void findAllDevices()
{
destroyAllDevices();
try
{
for ( Webcam w : Webcam.getWebcams( 30, TimeUnit.SECONDS ) )
{
RegisterNewInput( w );
}
}
catch ( WebcamException | TimeoutException e )
{
e.printStackTrace();
}
}
public InputRegistry()
{
instance = this;
Webcam.addDiscoveryListener( this );
}
@Override
public void webcamFound( WebcamDiscoveryEvent arg0 )
{
RegisterNewInput( arg0.getWebcam() );
}
@Override
public void webcamGone( WebcamDiscoveryEvent arg0 )
{
for ( VideoInput i : inputs )
{
if ( i.getDevice().equals( arg0.getWebcam() ) )
inputs.remove( i );
}
}
public static void openAllDevices()
{
for ( VideoInput i : inputs )
{
i.open();
}
}
public static void closeAllDevices()
{
for ( VideoInput i : inputs )
{
i.close();
}
}
public static VideoInput get( int index )
{
try
{
return inputs.get( index );
}
catch ( ArrayIndexOutOfBoundsException e )
{
return null;
}
}
public static void RegisterNewInput( Webcam w )
{
for ( VideoInput i : inputs )
{
if ( i.getDevice().getDevice().getName().equals( w.getDevice().getName() ) )
return;
}
Loader.getLogger().info( "Adding VideoInput: " + w.getName() );
inputs.add( new VideoInput( w ) );
}
public static int getInputCount()
{
return inputs.size();
}
}