@Override
	public void run()
	{
		while(isRunning())
		{
			// check if audioFormat was updated
			if (getWasAudioFormatUpdated())
			{
				// audioFormat update; close line and reopen w/ new format
				sourceLine.stop();
				sourceLine.close();
				try
				{
					sourceLine.open(getAudioFormat());
					sourceLine.flush();
					maxBytesAvailable = sourceLine.available();
				}
				catch (LineUnavailableException e)
				{
					System.out.println("Line unavailable: " + e.getMessage());
				}
				sourceLine.start();
				unflagAudioFormatUpdate();
			}
			
			// connect to socket if needed
			try
			{
				socket.receive(packet);
				
				if (!connected)
				{
					socket.connect(packet.getAddress(), packet.getPort());
					
					// reduce timeout
					socket.setSoTimeout(1000);
					
					connected = true;
				}
					
			} 
			// if socket times out, assume client disconnected
			catch (SocketTimeoutException e)
			{
				System.out.println("Connection lost");
				stop();
			}
			
			catch (IOException e)
			{
				// unexpected exception
				stop();
			}
			
			int bytesRead = packet.getLength();
			
			/* buffer data if needed */
			if (!hasEnoughInStream() && !isBuffered())
			{
				// read data from packet into buffer
				System.arraycopy(packet.getData(), 0, audioDataBuffer, bytesBuffered, bytesRead);
				bytesBuffered += bytesRead;
			}
			
			/* put audio data into source line */
			else
			{
				/*
				 * read from buffer if there is data in it
				 * this should only happen once after each time buffering data
				 */
				if (bytesBuffered > 0)
				{
					sourceLine.write(audioDataBuffer, 0, bytesBuffered);
					bytesBuffered = 0;
				}
				
				/*
				 * if too far out of sync w/ client, discard pending audioData.
				 * this will sound shitty.. sorry :( 
				 */
				/*else if (isBehind())
				{
					System.out.println("fell out too far out of sync.. discarding data");
					sourceLine.drain();
				}*/
				
				// write info from packet
				sourceLine.write(packet.getData(), 0, bytesRead);
			}
			
		}
	}