001package net.bramp.ffmpeg.progress; 002 003import static com.google.common.base.Preconditions.checkNotNull; 004 005import com.google.common.net.InetAddresses; 006import java.io.IOException; 007import java.net.InetAddress; 008import java.net.URI; 009import java.net.URISyntaxException; 010import java.util.concurrent.CountDownLatch; 011import javax.annotation.CheckReturnValue; 012 013public abstract class AbstractSocketProgressParser implements ProgressParser { 014 015 final StreamProgressParser parser; 016 017 Thread thread; // Thread for handling incoming connections 018 019 public AbstractSocketProgressParser(ProgressListener listener) { 020 this.parser = new StreamProgressParser(listener); 021 } 022 023 /** 024 * Creates a URL to parse to FFmpeg based on the scheme, address and port. 025 * 026 * <p>TODO Move this method to somewhere better. 027 * 028 * @param scheme 029 * @param address 030 * @param port 031 * @return 032 * @throws URISyntaxException 033 */ 034 @CheckReturnValue 035 static URI createUri(String scheme, InetAddress address, int port) throws URISyntaxException { 036 checkNotNull(address); 037 return new URI( 038 scheme, 039 null /* userInfo */, 040 InetAddresses.toUriString(address), 041 port, 042 null /* path */, 043 null /* query */, 044 null /* fragment */); 045 } 046 047 @CheckReturnValue 048 protected abstract String getThreadName(); 049 050 protected abstract Runnable getRunnable(CountDownLatch startSignal); 051 052 /** 053 * Starts the ProgressParser waiting for progress. 054 * 055 * @exception IllegalThreadStateException if the parser was already started. 056 */ 057 @Override 058 public synchronized void start() { 059 if (thread != null) { 060 throw new IllegalThreadStateException("Parser already started"); 061 } 062 063 String name = getThreadName() + "(" + getUri().toString() + ")"; 064 065 CountDownLatch startSignal = new CountDownLatch(1); 066 Runnable runnable = getRunnable(startSignal); 067 068 thread = new Thread(runnable, name); 069 thread.start(); 070 071 // Block until the thread has started 072 try { 073 startSignal.await(); 074 } catch (InterruptedException e) { 075 Thread.currentThread().interrupt(); 076 } 077 } 078 079 @Override 080 public void stop() throws IOException { 081 if (thread != null) { 082 thread.interrupt(); // This unblocks processStream(); 083 084 try { 085 thread.join(); 086 } catch (InterruptedException e) { 087 Thread.currentThread().interrupt(); 088 } 089 } 090 } 091 092 @Override 093 public void close() throws IOException { 094 stop(); 095 } 096}