[StreamingAudio] Add PlayerViewController instead of using playerController outlet in AppDelegate.cs

This commit is contained in:
olegoid 2014-01-31 21:53:57 +04:00
Родитель 43dc5c9dbf
Коммит 453ce50ce7
3 изменённых файлов: 332 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,197 @@
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Net;
using MonoTouch.AudioToolbox;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace StreamingAudio
{
public partial class PlayerViewController : UIViewController
{
private NSTimer updatingTimer;
private StreamingPlayback player;
public Action<string> ErrorOccurred;
public string SourceUrl { get; private set; }
public PlayerOption PlayerOption { get; private set; }
public bool IsPlaying { get; private set; }
public PlayerViewController (PlayerOption playerOption, string sourceUrl) : base ("PlayerViewController", null)
{
PlayerOption = playerOption;
SourceUrl = sourceUrl;
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.View = View;
volumeSlider.TouchUpInside += SetVolume;
playPauseButton.TouchUpInside += PlayPauseButtonClickHandler;
}
private void SetVolume (object sender, EventArgs e)
{
if (player == null)
return;
player.Volume = volumeSlider.Value;
}
public override void ViewWillAppear (bool animated)
{
base.ViewWillAppear (animated);
Title = PlayerOption == PlayerOption.Stream ? "Stream " : "Stream & Save";
playPauseButton.TitleLabel.Text = "Pause";
timeLabel.Text = string.Empty;
AudioSession.Initialize ();
StartPlayback ();
IsPlaying = true;
}
public override void ViewDidDisappear (bool animated)
{
base.ViewDidDisappear (animated);
if (player != null)
player.Pause ();
}
private void PlayPauseButtonClickHandler (object sender, EventArgs e)
{
if (player == null)
return;
if (IsPlaying)
player.Pause ();
else
player.Play ();
var title = IsPlaying ? "Play" : "Pause";
playPauseButton.SetTitle (title, UIControlState.Normal);
playPauseButton.SetTitle (title, UIControlState.Selected);
IsPlaying = !IsPlaying;
}
private void StartPlayback ()
{
PreparePlayback ();
try {
var request = (HttpWebRequest)WebRequest.Create (SourceUrl);
request.BeginGetResponse (StreamDownloadedHandler, request);
} catch (Exception e) {
string.Format ("Error: {0}", e.ToString ());
}
}
private void RaiseErrorOccurredEvent (string message)
{
if (ErrorOccurred != null)
ErrorOccurred (message);
}
private void PreparePlayback ()
{
//The following line prevents the audio from stopping when the device autolocks
AudioSession.Category = AudioSessionCategory.MediaPlayback;
AudioSession.RoutingOverride = AudioSessionRoutingOverride.Speaker;
}
private void StreamDownloadedHandler (IAsyncResult result)
{
var buffer = new byte [8192];
int l = 0;
int inputStreamLength;
double sampleRate = 0;
Stream inputStream;
AudioQueueTimeline timeline = null;
var request = result.AsyncState as HttpWebRequest;
try {
var response = request.EndGetResponse (result);
var responseStream = response.GetResponseStream ();
if (PlayerOption == PlayerOption.StreamAndSave)
inputStream = GetQueueStream (responseStream);
else
inputStream = responseStream;
using (player = new StreamingPlayback ()) {
player.OutputReady += delegate {
timeline = player.OutputQueue.CreateTimeline ();
sampleRate = player.OutputQueue.SampleRate;
};
InvokeOnMainThread (delegate {
if (updatingTimer != null)
updatingTimer.Invalidate ();
updatingTimer = NSTimer.CreateRepeatingScheduledTimer (0.5, () => RepeatingAction (timeline, sampleRate));
});
while ((inputStreamLength = inputStream.Read (buffer, 0, buffer.Length)) != 0) {
l += inputStreamLength;
player.ParseBytes (buffer, inputStreamLength, false, l == (int)response.ContentLength);
InvokeOnMainThread (delegate {
progressBar.Progress = l / (float)response.ContentLength;
});
}
}
} catch (Exception e) {
RaiseErrorOccurredEvent ("Error fetching response stream\n" + e);
Debug.WriteLine (e);
InvokeOnMainThread (delegate {
if (NavigationController != null)
NavigationController.PopToRootViewController (true);
});
}
}
private void RepeatingAction (AudioQueueTimeline timeline, double sampleRate)
{
var queue = player.OutputQueue;
if (queue == null || timeline == null)
return;
bool disc = false;
var time = new AudioTimeStamp ();
queue.GetCurrentTime (timeline, ref time, ref disc);
playbackTime.Text = FormatTime (time.SampleTime / sampleRate);
}
private string FormatTime (double time)
{
double minutes = time / 60;
double seconds = time % 60;
return String.Format ("{0}:{1:D2}", (int)minutes, (int)seconds);
}
private Stream GetQueueStream (Stream responseStream)
{
var queueStream = new QueueStream (Environment.GetFolderPath (Environment.SpecialFolder.Personal) + "copy.mp3");
var t = new Thread ((x) => {
var tbuf = new byte [8192];
int count;
while ((count = responseStream.Read (tbuf, 0, tbuf.Length)) != 0)
queueStream.Push (tbuf, 0, count);
});
t.Start ();
return queueStream;
}
}
}

58
StreamingAudio/PlayerViewController.designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,58 @@
// WARNING
//
// This file has been generated automatically by Xamarin Studio to store outlets and
// actions made in the UI designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using MonoTouch.Foundation;
using System.CodeDom.Compiler;
namespace StreamingAudio
{
[Register ("PlayerViewController")]
partial class PlayerViewController
{
[Outlet]
MonoTouch.UIKit.UILabel playbackTime { get; set; }
[Outlet]
MonoTouch.UIKit.UIButton playPauseButton { get; set; }
[Outlet]
MonoTouch.UIKit.UIProgressView progressBar { get; set; }
[Outlet]
MonoTouch.UIKit.UILabel timeLabel { get; set; }
[Outlet]
MonoTouch.UIKit.UISlider volumeSlider { get; set; }
void ReleaseDesignerOutlets ()
{
if (playPauseButton != null) {
playPauseButton.Dispose ();
playPauseButton = null;
}
if (progressBar != null) {
progressBar.Dispose ();
progressBar = null;
}
if (timeLabel != null) {
timeLabel.Dispose ();
timeLabel = null;
}
if (volumeSlider != null) {
volumeSlider.Dispose ();
volumeSlider = null;
}
if (playbackTime != null) {
playbackTime.Dispose ();
playbackTime = null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="4514" systemVersion="13B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3747"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="PlayerViewController">
<connections>
<outlet property="playPauseButton" destination="SP7-sW-LfZ" id="McA-Ba-V84"/>
<outlet property="playbackTime" destination="C0l-Uf-RPu" id="Vmp-f6-0bR"/>
<outlet property="progressBar" destination="wG9-jD-zWY" id="LLd-y6-2Hr"/>
<outlet property="timeLabel" destination="C0l-Uf-RPu" id="Rg0-f5-qgw"/>
<outlet property="view" destination="3Mt-jV-nDm" id="2EV-Wk-Xji"/>
<outlet property="volumeSlider" destination="Ka9-Cy-B6c" id="LVw-eX-fdw"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="3Mt-jV-nDm">
<rect key="frame" x="0.0" y="0.0" width="320" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<slider opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="1" minValue="0.0" maxValue="1" id="Ka9-Cy-B6c">
<rect key="frame" x="18" y="323" width="284" height="29"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</slider>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Download Progress:" lineBreakMode="tailTruncation" minimumFontSize="10" id="pEk-Dg-EIy">
<rect key="frame" x="20" y="85" width="154" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Volume:" lineBreakMode="tailTruncation" minimumFontSize="10" id="wU8-p7-Dfc">
<rect key="frame" x="20" y="281" width="220" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<progressView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" id="wG9-jD-zWY">
<rect key="frame" x="20" y="134" width="280" height="2"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
</progressView>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Streaming audio:" lineBreakMode="tailTruncation" minimumFontSize="10" id="d3N-Vw-0MV">
<rect key="frame" x="20" y="20" width="130" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Sample Time:" lineBreakMode="tailTruncation" minimumFontSize="10" id="CqO-hs-cJP">
<rect key="frame" x="20" y="175" width="273" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="SP7-sW-LfZ">
<rect key="frame" x="124" y="372" width="72" height="37"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" name="Helvetica-Bold" family="Helvetica" pointSize="15"/>
<state key="normal" title="Pause">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
</button>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="Label" textAlignment="right" lineBreakMode="tailTruncation" minimumFontSize="10" id="C0l-Uf-RPu">
<rect key="frame" x="198" y="175" width="102" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</objects>
</document>