Skip to content

Commit

Permalink
adjust on Audio Handler for iOS 5
Browse files Browse the repository at this point in the history
  • Loading branch information
pentateu committed Jun 18, 2012
1 parent c66701b commit 23b4881
Show file tree
Hide file tree
Showing 13 changed files with 165 additions and 31 deletions.
9 changes: 9 additions & 0 deletions .classpath
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry excluding="**" including="**/*.java" kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER"/>
<classpathentry kind="output" path="target/classes"/>
</classpath>
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@

target/
23 changes: 23 additions & 0 deletions .project
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>DroidAirPlay</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
</projectDescription>
6 changes: 6 additions & 0 deletions .settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
#Mon Jun 18 20:52:19 NZST 2012
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/main/resources=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8
6 changes: 6 additions & 0 deletions .settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
#Mon Jun 18 20:52:19 NZST 2012
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.source=1.6
5 changes: 5 additions & 0 deletions .settings/org.eclipse.m2e.core.prefs
@@ -0,0 +1,5 @@
#Mon Jun 18 20:51:15 NZST 2012
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
10 changes: 5 additions & 5 deletions pom.xml
Expand Up @@ -3,13 +3,13 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.phlo</groupId>
<artifactId>AirReceiver</artifactId>
<version>1.2</version>
<groupId>nz.co.iswe</groupId>
<artifactId>DroidAirPlay</artifactId>
<version>0.1</version>
<packaging>jar</packaging>

<name>AirReceiver</name>
<url>https://github.com/fgp/AirReceiver</url>
<name> DroidAirPlay </name>
<url>https://github.com/pentateu/DroidAirPlay</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
Expand Up @@ -15,26 +15,66 @@
* along with AirReceiver. If not, see <http://www.gnu.org/licenses/>.
*/

package org.phlo.AirReceiver;

import java.net.*;
import java.nio.charset.*;
import java.util.*;
package nz.co.iswe.droidairplay.audio;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Deque;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.*;
import javax.crypto.spec.*;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.group.*;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelDownstreamHandler;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.UpstreamMessageEvent;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
import org.jboss.netty.handler.codec.http.*;
import org.jboss.netty.handler.codec.rtsp.*;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.rtsp.RtspResponseStatuses;
import org.jboss.netty.handler.codec.rtsp.RtspVersions;
import org.phlo.AirReceiver.AirReceiver;
import org.phlo.AirReceiver.AirTunesCrytography;
import org.phlo.AirReceiver.AudioOutputQueue;
import org.phlo.AirReceiver.AudioStreamInformationProvider;
import org.phlo.AirReceiver.Base64;
import org.phlo.AirReceiver.ExceptionLoggingHandler;
import org.phlo.AirReceiver.ProtocolException;
import org.phlo.AirReceiver.RaopRtpAudioAlacDecodeHandler;
import org.phlo.AirReceiver.RaopRtpAudioDecryptionHandler;
import org.phlo.AirReceiver.RaopRtpDecodeHandler;
import org.phlo.AirReceiver.RaopRtpPacket;
import org.phlo.AirReceiver.RaopRtpRetransmitRequestHandler;
import org.phlo.AirReceiver.RaopRtpTimingHandler;
import org.phlo.AirReceiver.RaopRtspMethods;
import org.phlo.AirReceiver.RtpEncodeHandler;
import org.phlo.AirReceiver.RtpLoggingHandler;

/**
* Handles the configuration, creation and destruction of RTP channels.
Expand Down Expand Up @@ -267,7 +307,7 @@ else if (RaopRtspMethods.GET_PARAMETER.equals(method)) {
* <attribute>=<value>
* }
*/
private static Pattern s_pattern_sdp_line = Pattern.compile("^([a-z])=(.*)$");
protected static Pattern s_pattern_sdp_line = Pattern.compile("^([a-z])=(.*)$");

/**
* SDP attribute {@code m}. Format is
Expand All @@ -279,7 +319,7 @@ else if (RaopRtspMethods.GET_PARAMETER.equals(method)) {
* RAOP/AirTunes always required {@code <media>=audio, <transport>=RTP/AVP}
* and only a single format is allowed. The port is ignored.
*/
private static Pattern s_pattern_sdp_m = Pattern.compile("^audio ([^ ]+) RTP/AVP ([0-9]+)$");
protected static Pattern s_pattern_sdp_m = Pattern.compile("^audio ([^ ]+) RTP/AVP ([0-9]+)$");

/**
* SDP attribute {@code a}. Format is
Expand All @@ -295,10 +335,12 @@ else if (RaopRtspMethods.GET_PARAMETER.equals(method)) {
* <li> {@code <attribute>=rtpmap}
* <li> {@code <attribute>=fmtp}
* <li> {@code <attribute>=rsaaeskey}
* <li> {@code <attribute>=aesiv}
* <li> {@code <attribute>=aesiv}
*
* <li> {@code <attribute>=min-latency}
* </ul>
*/
private static Pattern s_pattern_sdp_a = Pattern.compile("^([a-z]+):(.*)$");
protected static Pattern s_pattern_sdp_a = Pattern.compile("^(\\w+):?(.*)$"); //changed to support dash in the attribute name

/**
* SDP {@code a} attribute {@code rtpmap}. Format is
Expand All @@ -324,11 +366,13 @@ public synchronized void announceReceived(final ChannelHandlerContext ctx, final
throws Exception
{
/* ANNOUNCE must contain stream information in SDP format */
if (!req.containsHeader("Content-Type"))
if ( ! req.containsHeader("Content-Type")){
throw new ProtocolException("No Content-Type header");
if (!"application/sdp".equals(req.getHeader("Content-Type")))
}
if (!"application/sdp".equals(req.getHeader("Content-Type"))){
throw new ProtocolException("Invalid Content-Type header, expected application/sdp but got " + req.getHeader("Content-Type"));

}

reset();

/* Get SDP stream information */
Expand All @@ -343,11 +387,11 @@ public synchronized void announceReceived(final ChannelHandlerContext ctx, final

for(final String line: dsp.split("\n")) {
/* Split SDP line into attribute and setting */
final Matcher line_matcher = s_pattern_sdp_line.matcher(line);
if (!line_matcher.matches())
final Matcher lineMatcher = s_pattern_sdp_line.matcher(line);
if (!lineMatcher.matches())
throw new ProtocolException("Cannot parse SDP line " + line);
final char attribute = line_matcher.group(1).charAt(0);
final String setting = line_matcher.group(2);
final char attribute = lineMatcher.group(1).charAt(0);
final String setting = lineMatcher.group(2);

/* Handle attributes */
switch (attribute) {
Expand All @@ -360,10 +404,15 @@ public synchronized void announceReceived(final ChannelHandlerContext ctx, final
break;

case 'a':
s_logger.info("setting: " + setting);

/* Attribute a. Defines various session properties */
final Matcher a_matcher = s_pattern_sdp_a.matcher(setting);
if (!a_matcher.matches())

if ( ! a_matcher.matches() ){
throw new ProtocolException("Cannot parse SDP " + attribute + "'s setting " + setting);
}

final String key = a_matcher.group(1);
final String value = a_matcher.group(2);

Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/phlo/AirReceiver/AudioOutputQueue.java
Expand Up @@ -323,7 +323,7 @@ private void appendFrames(final byte[] samples, int off, int len) {
}
}

AudioOutputQueue(final AudioStreamInformationProvider streamInfoProvider) throws LineUnavailableException {
public AudioOutputQueue(final AudioStreamInformationProvider streamInfoProvider) throws LineUnavailableException {
final AudioFormat audioFormat = streamInfoProvider.getAudioFormat();

/* OSX does not support unsigned PCM lines. We thust always request
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/org/phlo/AirReceiver/ProtocolException.java
Expand Up @@ -19,7 +19,7 @@

@SuppressWarnings("serial")
public class ProtocolException extends Exception {
ProtocolException(final String message) {
public ProtocolException(final String message) {
super(message);
}
}
Expand Up @@ -17,6 +17,8 @@

package org.phlo.AirReceiver;

import nz.co.iswe.droidairplay.audio.RaopAudioHandler;

import org.jboss.netty.channel.*;
import org.jboss.netty.handler.codec.rtsp.*;

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/logging.properties
Expand Up @@ -4,6 +4,7 @@ java.util.logging.ConsoleHandler.level=ALL

.level=WARNING
org.phlo.AirReceiver.level=INFO
nz.co.iswe.droidairplay.level=INFO
#javax.jmdns.level=ALL
#org.phlo.AirReceiver.RaopRtpTimingHandler.level=FINEST
#org.phlo.AirReceiver.AudioOutputQueue.level=FINE
Expand Down
@@ -0,0 +1,31 @@
package nz.co.iswe.droidairplay.audio;

import java.util.regex.Matcher;

import junit.framework.Assert;

import org.junit.Test;


public class RaopAudioHandlerTest {

@Test
public void testPatternSdpLine(){

String line = "rtpmap:value";
Matcher matcher = RaopAudioHandler.s_pattern_sdp_a.matcher(line);
Assert.assertTrue(matcher.matches());


line = "min-latency:11400";
matcher = RaopAudioHandler.s_pattern_sdp_a.matcher(line);
Assert.assertTrue(matcher.matches());

//line = "min:latency:11400";
//matcher = RaopAudioHandler.s_pattern_sdp_a.matcher(line);
//Assert.assertFalse(matcher.matches());

}


}

0 comments on commit 23b4881

Please sign in to comment.