You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by pu...@apache.org on 2013/06/14 20:53:55 UTC
[1/5] wp7 commit: Broke AudioFormatsHelper back into the 2 classes
that use it to avoid plugin dependency
Updated Branches:
refs/heads/master 2c477f436 -> 6f7e2865e
Broke AudioFormatsHelper back into the 2 classes that use it to avoid plugin dependency
Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/89bc040a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/89bc040a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/89bc040a
Branch: refs/heads/master
Commit: 89bc040a17e3fdfda1dd0677741458c20b459b96
Parents: 837f7cc
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Tue Jun 11 14:25:28 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Tue Jun 11 14:25:28 2013 -0700
----------------------------------------------------------------------
templates/standalone/Plugins/AudioPlayer.cs | 34 +++++++++++++++++---
.../standalone/Plugins/UI/AudioRecorder.xaml.cs | 22 +++++++++++--
2 files changed, 49 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/89bc040a/templates/standalone/Plugins/AudioPlayer.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/AudioPlayer.cs b/templates/standalone/Plugins/AudioPlayer.cs
index a83be5b..6c94016 100644
--- a/templates/standalone/Plugins/AudioPlayer.cs
+++ b/templates/standalone/Plugins/AudioPlayer.cs
@@ -27,6 +27,7 @@ using System.Windows.Resources;
namespace WPCordovaClassLib.Cordova.Commands
{
+
/// <summary>
/// Implements audio record and play back functionality.
/// </summary>
@@ -62,6 +63,7 @@ namespace WPCordovaClassLib.Cordova.Commands
#endregion
+
/// <summary>
/// The AudioHandler object
/// </summary>
@@ -77,6 +79,8 @@ namespace WPCordovaClassLib.Cordova.Commands
/// </summary>
DispatcherTimer dtXna;
+
+
/// <summary>
/// Output buffer
/// </summary>
@@ -128,6 +132,8 @@ namespace WPCordovaClassLib.Cordova.Commands
this.id = id;
}
+
+
/// <summary>
/// Destroys player and stop audio playing or recording
/// </summary>
@@ -194,8 +200,26 @@ namespace WPCordovaClassLib.Cordova.Commands
this.recorder.BufferDuration = TimeSpan.FromMilliseconds(500);
this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)];
this.recorder.BufferReady += new EventHandler<EventArgs>(recorderBufferReady);
- this.memoryStream = new MemoryStream();
- this.memoryStream.InitializeWavStream(this.recorder.SampleRate);
+ MemoryStream stream = new MemoryStream();
+ this.memoryStream = stream;
+ int numBits = 16;
+ int numBytes = numBits / 8;
+
+ // inline version from AudioFormatsHelper
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("RIFF"), 0, 4);
+ stream.Write(BitConverter.GetBytes(0), 0, 4);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("WAVE"), 0, 4);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("fmt "), 0, 4);
+ stream.Write(BitConverter.GetBytes(16), 0, 4);
+ stream.Write(BitConverter.GetBytes((short)1), 0, 2);
+ stream.Write(BitConverter.GetBytes((short)1), 0, 2);
+ stream.Write(BitConverter.GetBytes(this.recorder.SampleRate), 0, 4);
+ stream.Write(BitConverter.GetBytes(this.recorder.SampleRate * numBytes), 0, 4);
+ stream.Write(BitConverter.GetBytes((short)(numBytes)), 0, 2);
+ stream.Write(BitConverter.GetBytes((short)(numBits)), 0, 2);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("data"), 0, 4);
+ stream.Write(BitConverter.GetBytes(0), 0, 4);
+
this.recorder.Start();
FrameworkDispatcher.Update();
this.SetState(PlayerState_Running);
@@ -284,7 +308,7 @@ namespace WPCordovaClassLib.Cordova.Commands
{
this.player.Stop(); // stop it!
}
-
+
this.player.Source = null; // Garbage collect it.
this.player.MediaOpened += MediaOpened;
this.player.MediaEnded += MediaEnded;
@@ -312,7 +336,7 @@ namespace WPCordovaClassLib.Cordova.Commands
{
using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
{
- byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);
+ byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);
string[] dirParts = filePath.Split('/');
string dirName = "";
@@ -586,7 +610,7 @@ namespace WPCordovaClassLib.Cordova.Commands
//TODO: log or do something else
throw;
}
- }
+ }
#region Xna loop
/// <summary>
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/89bc040a/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs b/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
index bc8ba6f..74fb846 100644
--- a/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
+++ b/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
@@ -122,8 +122,25 @@ namespace WPCordovaClassLib.Cordova.UI
this.buffer = new byte[microphone.GetSampleSizeInBytes(this.microphone.BufferDuration)];
this.microphone.BufferReady += new EventHandler<EventArgs>(MicrophoneBufferReady);
- this.memoryStream = new MemoryStream();
- this.memoryStream.InitializeWavStream(this.microphone.SampleRate);
+ MemoryStream stream = new MemoryStream();
+ this.memoryStream = stream;
+ int numBits = 16;
+ int numBytes = numBits / 8;
+
+ // inline version from AudioFormatsHelper
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("RIFF"), 0, 4);
+ stream.Write(BitConverter.GetBytes(0), 0, 4);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("WAVE"), 0, 4);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("fmt "), 0, 4);
+ stream.Write(BitConverter.GetBytes(16), 0, 4);
+ stream.Write(BitConverter.GetBytes((short)1), 0, 2);
+ stream.Write(BitConverter.GetBytes((short)1), 0, 2);
+ stream.Write(BitConverter.GetBytes(this.microphone.SampleRate), 0, 4);
+ stream.Write(BitConverter.GetBytes(this.microphone.SampleRate * numBytes), 0, 4);
+ stream.Write(BitConverter.GetBytes((short)(numBytes)), 0, 2);
+ stream.Write(BitConverter.GetBytes((short)(numBits)), 0, 2);
+ stream.Write(System.Text.Encoding.UTF8.GetBytes("data"), 0, 4);
+ stream.Write(BitConverter.GetBytes(0), 0, 4);
this.duration = new TimeSpan(0);
@@ -302,5 +319,6 @@ namespace WPCordovaClassLib.Cordova.UI
dtXna = null;
}
}
+
}
}
\ No newline at end of file
[3/5] wp7 commit: Missed a function there ... added it to Audio
Player and Recorder.
Posted by pu...@apache.org.
Missed a function there ... added it to Audio Player and Recorder.
Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/fe2026e3
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/fe2026e3
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/fe2026e3
Branch: refs/heads/master
Commit: fe2026e3a61cb0266fcdebfbdca4e2dfddf3719a
Parents: 12474d1
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Tue Jun 11 14:41:23 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Tue Jun 11 14:41:23 2013 -0700
----------------------------------------------------------------------
templates/standalone/Plugins/AudioPlayer.cs | 9 +++++++--
templates/standalone/Plugins/UI/AudioRecorder.xaml.cs | 8 +++++++-
2 files changed, 14 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/fe2026e3/templates/standalone/Plugins/AudioPlayer.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/AudioPlayer.cs b/templates/standalone/Plugins/AudioPlayer.cs
index 6c94016..fe85e6b 100644
--- a/templates/standalone/Plugins/AudioPlayer.cs
+++ b/templates/standalone/Plugins/AudioPlayer.cs
@@ -579,12 +579,17 @@ namespace WPCordovaClassLib.Cordova.Commands
/// <returns></returns>
private void SaveAudioClipToLocalStorage()
{
- if (this.memoryStream == null || this.memoryStream.Length <= 0)
+ if (memoryStream == null || memoryStream.Length <= 0)
{
return;
}
- this.memoryStream.UpdateWavStream();
+ long position = memoryStream.Position;
+ memoryStream.Seek(4, SeekOrigin.Begin);
+ memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 8), 0, 4);
+ memoryStream.Seek(40, SeekOrigin.Begin);
+ memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 44), 0, 4);
+ memoryStream.Seek(position, SeekOrigin.Begin);
try
{
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/fe2026e3/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs b/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
index 74fb846..6ff0b5c 100644
--- a/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
+++ b/templates/standalone/Plugins/UI/AudioRecorder.xaml.cs
@@ -251,7 +251,13 @@ namespace WPCordovaClassLib.Cordova.UI
return new AudioResult(TaskResult.Cancel);
}
- this.memoryStream.UpdateWavStream();
+ //this.memoryStream.UpdateWavStream();
+ long position = memoryStream.Position;
+ memoryStream.Seek(4, SeekOrigin.Begin);
+ memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 8), 0, 4);
+ memoryStream.Seek(40, SeekOrigin.Begin);
+ memoryStream.Write(BitConverter.GetBytes((int)memoryStream.Length - 44), 0, 4);
+ memoryStream.Seek(position, SeekOrigin.Begin);
// save audio data to local isolated storage
[5/5] wp7 commit: Merge branch 'master' of
github.com:purplecabbage/cordova-wp7
Posted by pu...@apache.org.
Merge branch 'master' of github.com:purplecabbage/cordova-wp7
Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/6f7e2865
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/6f7e2865
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/6f7e2865
Branch: refs/heads/master
Commit: 6f7e2865e39b90c04add0e6366a39e984d665053
Parents: 2c477f4 6777eed
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Fri Jun 14 11:53:02 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Fri Jun 14 11:53:02 2013 -0700
----------------------------------------------------------------------
framework/WPCordovaClassLib.csproj | 12 +-
templates/standalone/CordovaAppProj.csproj | 14 +-
.../standalone/CordovaSourceDictionary.xml | 2 +-
templates/standalone/Plugins/ImageExifHelper.cs | 209 -------------------
templates/standalone/cordovalib/BaseCommand.cs | 187 +++++++++++++++++
.../cordovalib/Commands/BaseCommand.cs | 187 -----------------
.../standalone/cordovalib/ImageExifHelper.cs | 209 +++++++++++++++++++
7 files changed, 410 insertions(+), 410 deletions(-)
----------------------------------------------------------------------
[4/5] wp7 commit: Moved some stuff around the proj,
for simplicity with plugins
Posted by pu...@apache.org.
Moved some stuff around the proj, for simplicity with plugins
Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/6777eed8
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/6777eed8
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/6777eed8
Branch: refs/heads/master
Commit: 6777eed8d5bbaf92a5db2970f68c22d7442c35e6
Parents: fe2026e
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Tue Jun 11 15:20:42 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Tue Jun 11 15:20:42 2013 -0700
----------------------------------------------------------------------
framework/WPCordovaClassLib.csproj | 12 +-
templates/standalone/CordovaAppProj.csproj | 14 +-
.../standalone/CordovaSourceDictionary.xml | 2 +-
templates/standalone/Plugins/ImageExifHelper.cs | 209 -------------------
templates/standalone/cordovalib/BaseCommand.cs | 187 +++++++++++++++++
.../cordovalib/Commands/BaseCommand.cs | 187 -----------------
.../standalone/cordovalib/ImageExifHelper.cs | 209 +++++++++++++++++++
7 files changed, 410 insertions(+), 410 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/framework/WPCordovaClassLib.csproj
----------------------------------------------------------------------
diff --git a/framework/WPCordovaClassLib.csproj b/framework/WPCordovaClassLib.csproj
index 1292286..b8f76ae 100644
--- a/framework/WPCordovaClassLib.csproj
+++ b/framework/WPCordovaClassLib.csproj
@@ -80,15 +80,15 @@
<Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="..\templates\standalone\cordovalib\BaseCommand.cs">
+ <Link>CordovaLib\BaseCommand.cs</Link>
+ </Compile>
<Compile Include="..\templates\standalone\cordovalib\BrowserMouseHelper.cs">
<Link>CordovaLib\BrowserMouseHelper.cs</Link>
</Compile>
<Compile Include="..\templates\standalone\cordovalib\CommandFactory.cs">
<Link>CordovaLib\CommandFactory.cs</Link>
</Compile>
- <Compile Include="..\templates\standalone\cordovalib\Commands\BaseCommand.cs">
- <Link>CordovaLib\Commands\BaseCommand.cs</Link>
- </Compile>
<Compile Include="..\templates\standalone\cordovalib\ConfigHandler.cs">
<Link>CordovaLib\ConfigHandler.cs</Link>
</Compile>
@@ -102,6 +102,9 @@
<Compile Include="..\templates\standalone\cordovalib\DOMStorageHelper.cs">
<Link>CordovaLib\DOMStorageHelper.cs</Link>
</Compile>
+ <Compile Include="..\templates\standalone\cordovalib\ImageExifHelper.cs">
+ <Link>CordovaLib\ImageExifHelper.cs</Link>
+ </Compile>
<Compile Include="..\templates\standalone\cordovalib\JSON\JsonHelper.cs">
<Link>CordovaLib\JSON\JsonHelper.cs</Link>
</Compile>
@@ -159,9 +162,6 @@
<Compile Include="..\templates\standalone\Plugins\Globalization.cs">
<Link>CordovaLib\Plugins\Globalization.cs</Link>
</Compile>
- <Compile Include="..\templates\standalone\Plugins\ImageExifHelper.cs">
- <Link>CordovaLib\Plugins\ImageExifHelper.cs</Link>
- </Compile>
<Compile Include="..\templates\standalone\Plugins\InAppBrowser.cs">
<Link>CordovaLib\Plugins\InAppBrowser.cs</Link>
</Compile>
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/CordovaAppProj.csproj
----------------------------------------------------------------------
diff --git a/templates/standalone/CordovaAppProj.csproj b/templates/standalone/CordovaAppProj.csproj
index 0bfcad2..8434a77 100644
--- a/templates/standalone/CordovaAppProj.csproj
+++ b/templates/standalone/CordovaAppProj.csproj
@@ -84,15 +84,16 @@
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
+ <Compile Include="cordovalib\BaseCommand.cs" />
<Compile Include="cordovalib\BrowserMouseHelper.cs" />
<Compile Include="cordovalib\CommandFactory.cs" />
- <Compile Include="cordovalib\Commands\BaseCommand.cs" />
<Compile Include="cordovalib\ConfigHandler.cs" />
<Compile Include="cordovalib\CordovaCommandCall.cs" />
<Compile Include="cordovalib\CordovaView.xaml.cs">
<DependentUpon>CordovaView.xaml</DependentUpon>
</Compile>
<Compile Include="cordovalib\DOMStorageHelper.cs" />
+ <Compile Include="cordovalib\ImageExifHelper.cs" />
<Compile Include="cordovalib\JSON\JsonHelper.cs" />
<Compile Include="cordovalib\NativeExecution.cs" />
<Compile Include="cordovalib\OrientationHelper.cs" />
@@ -179,24 +180,23 @@
<Compile Include="Plugins\FileTransfer.cs" />
<Compile Include="Plugins\GeoLocation.cs" />
<Compile Include="Plugins\Globalization.cs" />
- <Compile Include="Plugins\ImageExifHelper.cs" />
<Compile Include="Plugins\InAppBrowser.cs" />
<Compile Include="Plugins\Media.cs" />
<Compile Include="Plugins\MimeTypeMapper.cs" />
<Compile Include="Plugins\NetworkStatus.cs" />
<Compile Include="Plugins\Notification.cs" />
<Compile Include="Plugins\UI\AudioCaptureTask.cs" />
- <Compile Include="Plugins\UI\AudioRecorder.xaml.cs" >
+ <Compile Include="Plugins\UI\AudioRecorder.xaml.cs">
<DependentUpon>AudioRecorder.xaml</DependentUpon>
</Compile>
- <Compile Include="Plugins\UI\ImageCapture.xaml.cs" >
+ <Compile Include="Plugins\UI\ImageCapture.xaml.cs">
<DependentUpon>ImageCapture.xaml</DependentUpon>
</Compile>
- <Compile Include="Plugins\UI\NotificationBox.xaml.cs" >
+ <Compile Include="Plugins\UI\NotificationBox.xaml.cs">
<DependentUpon>NotificationBox.xaml</DependentUpon>
</Compile>
<Compile Include="Plugins\UI\VideoCaptureTask.cs" />
- <Compile Include="Plugins\UI\VideoRecorder.xaml.cs" >
+ <Compile Include="Plugins\UI\VideoRecorder.xaml.cs">
<DependentUpon>VideoRecorder.xaml</DependentUpon>
</Compile>
</ItemGroup>
@@ -235,4 +235,4 @@
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
-</Project>
+</Project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/CordovaSourceDictionary.xml
----------------------------------------------------------------------
diff --git a/templates/standalone/CordovaSourceDictionary.xml b/templates/standalone/CordovaSourceDictionary.xml
index 74f51b7..ea05ca7 100644
--- a/templates/standalone/CordovaSourceDictionary.xml
+++ b/templates/standalone/CordovaSourceDictionary.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This file is auto-generated, do not edit! -jm -->
<CordovaSourceDictionary>
- <FilePath Value="www\cordova-2.6.0.js"/>
+ <FilePath Value="www\cordova.js"/>
<FilePath Value="www\index.html"/>
<FilePath Value="www\css\index.css"/>
<FilePath Value="www\img\logo.png"/>
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/Plugins/ImageExifHelper.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/Plugins/ImageExifHelper.cs b/templates/standalone/Plugins/ImageExifHelper.cs
deleted file mode 100644
index 62b6462..0000000
--- a/templates/standalone/Plugins/ImageExifHelper.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-*/
-
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.Windows.Media.Imaging;
-
-namespace WPCordovaClassLib.Cordova.Commands
-{
- public class ImageExifOrientation
- {
- public const int Portrait = 1;
- public const int PortraitUpsideDown = 3;
- public const int LandscapeLeft = 6;
- public const int LandscapeRight = 8;
- }
-
- public class ImageExifHelper
- {
-
- public static Stream RotateStream(Stream stream, int angle)
- {
- stream.Position = 0;
- if (angle % 90 != 0 || angle < 0)
- {
- throw new ArgumentException();
- }
- if (angle % 360 == 0)
- {
- return stream;
- }
-
- angle = angle % 360;
-
- BitmapImage bitmap = new BitmapImage();
- bitmap.SetSource(stream);
- WriteableBitmap wbSource = new WriteableBitmap(bitmap);
-
- WriteableBitmap wbTarget = null;
-
- int srcPixelWidth = wbSource.PixelWidth;
- int srcPixelHeight = wbSource.PixelHeight;
-
- if (angle % 180 == 0)
- {
- wbTarget = new WriteableBitmap(srcPixelWidth, srcPixelHeight);
- }
- else
- {
- wbTarget = new WriteableBitmap(srcPixelHeight, srcPixelWidth);
- }
-
- int destPixelWidth = wbTarget.PixelWidth;
- int[] srcPxls = wbSource.Pixels;
- int[] destPxls = wbTarget.Pixels;
-
- // this ugly if/else is to avoid a conditional check for every pixel
- if (angle == 90)
- {
- for (int x = 0; x < srcPixelWidth; x++)
- {
- for (int y = 0; y < srcPixelHeight; y++)
- {
- destPxls[(srcPixelHeight - y - 1) + (x * destPixelWidth)] = srcPxls[x + y * srcPixelWidth];
- }
- }
- }
- else if (angle == 180)
- {
- for (int x = 0; x < srcPixelWidth; x++)
- {
- for (int y = 0; y < srcPixelHeight; y++)
- {
- destPxls[(srcPixelWidth - x - 1) + (srcPixelHeight - y - 1) * srcPixelWidth] = srcPxls[x + y * srcPixelWidth];
- }
- }
- }
- else if (angle == 270)
- {
- for (int x = 0; x < srcPixelWidth; x++)
- {
- for (int y = 0; y < srcPixelHeight; y++)
- {
- destPxls[y + (srcPixelWidth - x - 1) * destPixelWidth] = srcPxls[x + y * srcPixelWidth];
- }
- }
- }
-
- MemoryStream targetStream = new MemoryStream();
- wbTarget.SaveJpeg(targetStream, destPixelWidth, wbTarget.PixelHeight, 0, 100);
- return targetStream;
- }
-
- public static int getImageOrientationFromStream(Stream imgStream)
- {
-
- // 0xFFD8 : jpgHeader
- // 0xFFE1 :
- // 0x???? : length of exif data
- // 0x????, 0x???? : Chars 'E','x','i','f'
- // 0x0000 : 2 empty bytes
- // <== mark beginning of tags SIZE:ID:VALUE
- // 0x???? : 'II' or 'MM' for Intel or Motorola ( always getting II on my WP7 devices ), determines littleEndian-ness
- // 0x002A : marker value
- // 0x???? : offset to the Image File Data
-
- // XXXX possible space before actual tag data ... we skip to mark + offset
-
- // 0x???? number of exif tags present
-
- // make sure we are at the beginning
- imgStream.Seek(0, SeekOrigin.Begin);
- BinaryReader reader = new BinaryReader(imgStream);
-
- byte[] jpgHdr = reader.ReadBytes(2); // always (0xFFD8)
-
- byte start = reader.ReadByte(); // 0xFF
- byte index = reader.ReadByte(); // 0xE1
-
- while (start == 0xFF && index != 0xE1) // This never seems to happen, todo: optimize
- {
- // Get the data length
- ushort dLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
- // skip along
- reader.ReadBytes(dLen - 2);
- start = reader.ReadByte();
- index = reader.ReadByte();
- }
-
- // It's only success if we found the 0xFFE1 marker
- if (start != 0xFF || index != 0xE1)
- {
- // throw new Exception("Could not find Exif data block");
- Debug.WriteLine("Did not find EXIF data");
- return 0;
- }
-
- // read 2 byte length of EXIF data
- ushort exifLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
- String exif = ""; // build the string
- for (var n = 0; n < 4; n++)
- {
- exif += reader.ReadChar();
- }
- if (exif != "Exif")
- {
- // did not find exif data ...
- Debug.WriteLine("Did not find EXIF data");
- return 0;
- }
-
- // read 2 empty bytes
- //ushort emptyBytes = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
- reader.ReadBytes(2);
-
- long headerMark = reader.BaseStream.Position; // where are we now <==
-
- //bool isLEndian = (reader.ReadChar() + "" + reader.ReadChar()) == "II";
- reader.ReadBytes(2); // 'II' or 'MM', but we don't care
-
- if (0x002A != BitConverter.ToUInt16(reader.ReadBytes(2), 0))
- {
- Debug.WriteLine("Error in data != 0x002A");
- return 0;
- }
-
- // Get the offset to the IFD (image file directory)
- ushort imgOffset = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
-
- imgStream.Position = headerMark + imgOffset;
- ushort tagCount = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
- for (ushort x = 0; x < tagCount; x++)
- {
- // Orientation = 0x112, aka 274
- if (0x112 == BitConverter.ToUInt16(reader.ReadBytes(2), 0))
- {
- ushort dType = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
- // don't care ..
- uint comps = reader.ReadUInt32();
- byte[] tagData = reader.ReadBytes(4);
- int orientation = (int)tagData[0];
- Debug.WriteLine("orientation = " + orientation.ToString());
- return orientation;
- // 6 means rotate clockwise 90 deg
- // 8 means rotate counter-clockwise 90 deg
- // 1 means all is good
- // 3 means flip vertical
- }
- // skip to the next item, 12 bytes each
- reader.BaseStream.Seek(10, SeekOrigin.Current);
- }
- return 0;
- }
-
- }
-}
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/cordovalib/BaseCommand.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/BaseCommand.cs b/templates/standalone/cordovalib/BaseCommand.cs
new file mode 100644
index 0000000..ac1d2d6
--- /dev/null
+++ b/templates/standalone/cordovalib/BaseCommand.cs
@@ -0,0 +1,187 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+using System;
+using System.Reflection;
+using Microsoft.Phone.Shell;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+ public abstract class BaseCommand : IDisposable
+ {
+ /*
+ * All commands + plugins must extend BaseCommand, because they are dealt with as BaseCommands in CordovaView.xaml.cs
+ *
+ **/
+
+ public event EventHandler<PluginResult> OnCommandResult;
+
+ public event EventHandler<ScriptCallback> OnCustomScript;
+
+ public string CurrentCommandCallbackId { get; set; }
+
+ public BaseCommand()
+ {
+ ResultHandlers = new Dictionary<string, EventHandler<PluginResult>>();
+ PhoneApplicationService service = PhoneApplicationService.Current;
+ service.Activated += this.OnResume;
+ service.Deactivated += this.OnPause;
+ }
+
+ protected Dictionary<string, EventHandler<PluginResult>> ResultHandlers;
+ public void AddResultHandler(string callbackId, EventHandler<PluginResult> handler)
+ {
+ ResultHandlers.Add(callbackId, handler);
+ }
+ public bool RemoveResultHandler(string callbackId)
+ {
+ return ResultHandlers.Remove(callbackId);
+ }
+
+ /*
+ * InvokeMethodNamed will call the named method of a BaseCommand subclass if it exists and pass the variable arguments list along.
+ **/
+
+ public object InvokeMethodNamed(string callbackId, string methodName, params object[] args)
+ {
+ //Debug.WriteLine(string.Format("InvokeMethodNamed:{0} callbackId:{1}",methodName,callbackId));
+ this.CurrentCommandCallbackId = callbackId;
+ return InvokeMethodNamed(methodName, args);
+ }
+
+ public object InvokeMethodNamed(string methodName, params object[] args)
+ {
+ MethodInfo mInfo = this.GetType().GetMethod(methodName);
+
+ if (mInfo != null)
+ {
+ // every function handles DispatchCommandResult by itself
+ return mInfo.Invoke(this, args);
+ }
+
+ // actually methodName could refer to a property
+ if (args == null || args.Length == 0 ||
+ (args.Length == 1 && "undefined".Equals(args[0])))
+ {
+ PropertyInfo pInfo = this.GetType().GetProperty(methodName);
+ if (pInfo != null)
+ {
+ object res = pInfo.GetValue(this, null);
+
+ DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res));
+
+ return res;
+ }
+ }
+
+ throw new MissingMethodException(methodName);
+
+ }
+
+ [Obsolete]
+ public void InvokeCustomScript(ScriptCallback script, bool removeHandler)
+ {
+ if (this.OnCustomScript != null)
+ {
+ this.OnCustomScript(this, script);
+ if (removeHandler)
+ {
+ this.OnCustomScript = null;
+ }
+ }
+ }
+
+ public void DispatchCommandResult()
+ {
+ this.DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
+ }
+
+ public void DispatchCommandResult(PluginResult result, string callbackId = "")
+ {
+ if (!string.IsNullOrEmpty(callbackId))
+ {
+ result.CallbackId = callbackId;
+ }
+ else
+ {
+ result.CallbackId = this.CurrentCommandCallbackId;
+ }
+
+ if (ResultHandlers.ContainsKey(result.CallbackId))
+ {
+ ResultHandlers[result.CallbackId](this, result);
+ }
+ else if (this.OnCommandResult != null)
+ {
+ OnCommandResult(this, result);
+ }
+ else
+ {
+ Debug.WriteLine("Failed to locate callback for id : " + result.CallbackId);
+ }
+
+ if (!result.KeepCallback)
+ {
+ this.Dispose();
+ }
+
+ }
+
+
+ /// <summary>
+ /// Occurs when the application is being deactivated.
+ /// </summary>
+ public virtual void OnReset() {}
+
+ /// <summary>
+ /// Occurs when the application is being loaded, and the config.xml has an autoload entry
+ /// </summary>
+ public virtual void OnInit() {}
+
+
+ /// <summary>
+ /// Occurs when the application is being deactivated.
+ /// </summary>
+ public virtual void OnPause(object sender, DeactivatedEventArgs e) {}
+
+ /// <summary>
+ /// Occurs when the application is being made active after previously being put
+ /// into a dormant state or tombstoned.
+ /// </summary>
+ public virtual void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e) {}
+
+ public void Dispose()
+ {
+ PhoneApplicationService service = PhoneApplicationService.Current;
+ service.Activated -= this.OnResume;
+ service.Deactivated -= this.OnPause;
+ this.OnCommandResult = null;
+ }
+
+ public static string GetBaseURL()
+ {
+#if CORDOVA_CLASSLIB
+ return "/WPCordovaClassLib;component/";
+#else
+ return "./";
+#endif
+ }
+ }
+
+
+
+}
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/cordovalib/Commands/BaseCommand.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/Commands/BaseCommand.cs b/templates/standalone/cordovalib/Commands/BaseCommand.cs
deleted file mode 100644
index ac1d2d6..0000000
--- a/templates/standalone/cordovalib/Commands/BaseCommand.cs
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-using System;
-using System.Reflection;
-using Microsoft.Phone.Shell;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-
-namespace WPCordovaClassLib.Cordova.Commands
-{
- public abstract class BaseCommand : IDisposable
- {
- /*
- * All commands + plugins must extend BaseCommand, because they are dealt with as BaseCommands in CordovaView.xaml.cs
- *
- **/
-
- public event EventHandler<PluginResult> OnCommandResult;
-
- public event EventHandler<ScriptCallback> OnCustomScript;
-
- public string CurrentCommandCallbackId { get; set; }
-
- public BaseCommand()
- {
- ResultHandlers = new Dictionary<string, EventHandler<PluginResult>>();
- PhoneApplicationService service = PhoneApplicationService.Current;
- service.Activated += this.OnResume;
- service.Deactivated += this.OnPause;
- }
-
- protected Dictionary<string, EventHandler<PluginResult>> ResultHandlers;
- public void AddResultHandler(string callbackId, EventHandler<PluginResult> handler)
- {
- ResultHandlers.Add(callbackId, handler);
- }
- public bool RemoveResultHandler(string callbackId)
- {
- return ResultHandlers.Remove(callbackId);
- }
-
- /*
- * InvokeMethodNamed will call the named method of a BaseCommand subclass if it exists and pass the variable arguments list along.
- **/
-
- public object InvokeMethodNamed(string callbackId, string methodName, params object[] args)
- {
- //Debug.WriteLine(string.Format("InvokeMethodNamed:{0} callbackId:{1}",methodName,callbackId));
- this.CurrentCommandCallbackId = callbackId;
- return InvokeMethodNamed(methodName, args);
- }
-
- public object InvokeMethodNamed(string methodName, params object[] args)
- {
- MethodInfo mInfo = this.GetType().GetMethod(methodName);
-
- if (mInfo != null)
- {
- // every function handles DispatchCommandResult by itself
- return mInfo.Invoke(this, args);
- }
-
- // actually methodName could refer to a property
- if (args == null || args.Length == 0 ||
- (args.Length == 1 && "undefined".Equals(args[0])))
- {
- PropertyInfo pInfo = this.GetType().GetProperty(methodName);
- if (pInfo != null)
- {
- object res = pInfo.GetValue(this, null);
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, res));
-
- return res;
- }
- }
-
- throw new MissingMethodException(methodName);
-
- }
-
- [Obsolete]
- public void InvokeCustomScript(ScriptCallback script, bool removeHandler)
- {
- if (this.OnCustomScript != null)
- {
- this.OnCustomScript(this, script);
- if (removeHandler)
- {
- this.OnCustomScript = null;
- }
- }
- }
-
- public void DispatchCommandResult()
- {
- this.DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
- }
-
- public void DispatchCommandResult(PluginResult result, string callbackId = "")
- {
- if (!string.IsNullOrEmpty(callbackId))
- {
- result.CallbackId = callbackId;
- }
- else
- {
- result.CallbackId = this.CurrentCommandCallbackId;
- }
-
- if (ResultHandlers.ContainsKey(result.CallbackId))
- {
- ResultHandlers[result.CallbackId](this, result);
- }
- else if (this.OnCommandResult != null)
- {
- OnCommandResult(this, result);
- }
- else
- {
- Debug.WriteLine("Failed to locate callback for id : " + result.CallbackId);
- }
-
- if (!result.KeepCallback)
- {
- this.Dispose();
- }
-
- }
-
-
- /// <summary>
- /// Occurs when the application is being deactivated.
- /// </summary>
- public virtual void OnReset() {}
-
- /// <summary>
- /// Occurs when the application is being loaded, and the config.xml has an autoload entry
- /// </summary>
- public virtual void OnInit() {}
-
-
- /// <summary>
- /// Occurs when the application is being deactivated.
- /// </summary>
- public virtual void OnPause(object sender, DeactivatedEventArgs e) {}
-
- /// <summary>
- /// Occurs when the application is being made active after previously being put
- /// into a dormant state or tombstoned.
- /// </summary>
- public virtual void OnResume(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e) {}
-
- public void Dispose()
- {
- PhoneApplicationService service = PhoneApplicationService.Current;
- service.Activated -= this.OnResume;
- service.Deactivated -= this.OnPause;
- this.OnCommandResult = null;
- }
-
- public static string GetBaseURL()
- {
-#if CORDOVA_CLASSLIB
- return "/WPCordovaClassLib;component/";
-#else
- return "./";
-#endif
- }
- }
-
-
-
-}
http://git-wip-us.apache.org/repos/asf/cordova-wp7/blob/6777eed8/templates/standalone/cordovalib/ImageExifHelper.cs
----------------------------------------------------------------------
diff --git a/templates/standalone/cordovalib/ImageExifHelper.cs b/templates/standalone/cordovalib/ImageExifHelper.cs
new file mode 100644
index 0000000..62b6462
--- /dev/null
+++ b/templates/standalone/cordovalib/ImageExifHelper.cs
@@ -0,0 +1,209 @@
+/*
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Windows.Media.Imaging;
+
+namespace WPCordovaClassLib.Cordova.Commands
+{
+ public class ImageExifOrientation
+ {
+ public const int Portrait = 1;
+ public const int PortraitUpsideDown = 3;
+ public const int LandscapeLeft = 6;
+ public const int LandscapeRight = 8;
+ }
+
+ public class ImageExifHelper
+ {
+
+ public static Stream RotateStream(Stream stream, int angle)
+ {
+ stream.Position = 0;
+ if (angle % 90 != 0 || angle < 0)
+ {
+ throw new ArgumentException();
+ }
+ if (angle % 360 == 0)
+ {
+ return stream;
+ }
+
+ angle = angle % 360;
+
+ BitmapImage bitmap = new BitmapImage();
+ bitmap.SetSource(stream);
+ WriteableBitmap wbSource = new WriteableBitmap(bitmap);
+
+ WriteableBitmap wbTarget = null;
+
+ int srcPixelWidth = wbSource.PixelWidth;
+ int srcPixelHeight = wbSource.PixelHeight;
+
+ if (angle % 180 == 0)
+ {
+ wbTarget = new WriteableBitmap(srcPixelWidth, srcPixelHeight);
+ }
+ else
+ {
+ wbTarget = new WriteableBitmap(srcPixelHeight, srcPixelWidth);
+ }
+
+ int destPixelWidth = wbTarget.PixelWidth;
+ int[] srcPxls = wbSource.Pixels;
+ int[] destPxls = wbTarget.Pixels;
+
+ // this ugly if/else is to avoid a conditional check for every pixel
+ if (angle == 90)
+ {
+ for (int x = 0; x < srcPixelWidth; x++)
+ {
+ for (int y = 0; y < srcPixelHeight; y++)
+ {
+ destPxls[(srcPixelHeight - y - 1) + (x * destPixelWidth)] = srcPxls[x + y * srcPixelWidth];
+ }
+ }
+ }
+ else if (angle == 180)
+ {
+ for (int x = 0; x < srcPixelWidth; x++)
+ {
+ for (int y = 0; y < srcPixelHeight; y++)
+ {
+ destPxls[(srcPixelWidth - x - 1) + (srcPixelHeight - y - 1) * srcPixelWidth] = srcPxls[x + y * srcPixelWidth];
+ }
+ }
+ }
+ else if (angle == 270)
+ {
+ for (int x = 0; x < srcPixelWidth; x++)
+ {
+ for (int y = 0; y < srcPixelHeight; y++)
+ {
+ destPxls[y + (srcPixelWidth - x - 1) * destPixelWidth] = srcPxls[x + y * srcPixelWidth];
+ }
+ }
+ }
+
+ MemoryStream targetStream = new MemoryStream();
+ wbTarget.SaveJpeg(targetStream, destPixelWidth, wbTarget.PixelHeight, 0, 100);
+ return targetStream;
+ }
+
+ public static int getImageOrientationFromStream(Stream imgStream)
+ {
+
+ // 0xFFD8 : jpgHeader
+ // 0xFFE1 :
+ // 0x???? : length of exif data
+ // 0x????, 0x???? : Chars 'E','x','i','f'
+ // 0x0000 : 2 empty bytes
+ // <== mark beginning of tags SIZE:ID:VALUE
+ // 0x???? : 'II' or 'MM' for Intel or Motorola ( always getting II on my WP7 devices ), determines littleEndian-ness
+ // 0x002A : marker value
+ // 0x???? : offset to the Image File Data
+
+ // XXXX possible space before actual tag data ... we skip to mark + offset
+
+ // 0x???? number of exif tags present
+
+ // make sure we are at the beginning
+ imgStream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(imgStream);
+
+ byte[] jpgHdr = reader.ReadBytes(2); // always (0xFFD8)
+
+ byte start = reader.ReadByte(); // 0xFF
+ byte index = reader.ReadByte(); // 0xE1
+
+ while (start == 0xFF && index != 0xE1) // This never seems to happen, todo: optimize
+ {
+ // Get the data length
+ ushort dLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+ // skip along
+ reader.ReadBytes(dLen - 2);
+ start = reader.ReadByte();
+ index = reader.ReadByte();
+ }
+
+ // It's only success if we found the 0xFFE1 marker
+ if (start != 0xFF || index != 0xE1)
+ {
+ // throw new Exception("Could not find Exif data block");
+ Debug.WriteLine("Did not find EXIF data");
+ return 0;
+ }
+
+ // read 2 byte length of EXIF data
+ ushort exifLen = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+ String exif = ""; // build the string
+ for (var n = 0; n < 4; n++)
+ {
+ exif += reader.ReadChar();
+ }
+ if (exif != "Exif")
+ {
+ // did not find exif data ...
+ Debug.WriteLine("Did not find EXIF data");
+ return 0;
+ }
+
+ // read 2 empty bytes
+ //ushort emptyBytes = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+ reader.ReadBytes(2);
+
+ long headerMark = reader.BaseStream.Position; // where are we now <==
+
+ //bool isLEndian = (reader.ReadChar() + "" + reader.ReadChar()) == "II";
+ reader.ReadBytes(2); // 'II' or 'MM', but we don't care
+
+ if (0x002A != BitConverter.ToUInt16(reader.ReadBytes(2), 0))
+ {
+ Debug.WriteLine("Error in data != 0x002A");
+ return 0;
+ }
+
+ // Get the offset to the IFD (image file directory)
+ ushort imgOffset = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+
+ imgStream.Position = headerMark + imgOffset;
+ ushort tagCount = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+ for (ushort x = 0; x < tagCount; x++)
+ {
+ // Orientation = 0x112, aka 274
+ if (0x112 == BitConverter.ToUInt16(reader.ReadBytes(2), 0))
+ {
+ ushort dType = BitConverter.ToUInt16(reader.ReadBytes(2), 0);
+ // don't care ..
+ uint comps = reader.ReadUInt32();
+ byte[] tagData = reader.ReadBytes(4);
+ int orientation = (int)tagData[0];
+ Debug.WriteLine("orientation = " + orientation.ToString());
+ return orientation;
+ // 6 means rotate clockwise 90 deg
+ // 8 means rotate counter-clockwise 90 deg
+ // 1 means all is good
+ // 3 means flip vertical
+ }
+ // skip to the next item, 12 bytes each
+ reader.BaseStream.Seek(10, SeekOrigin.Current);
+ }
+ return 0;
+ }
+
+ }
+}
[2/5] wp7 commit: Merge branch 'master' of
github.com:purplecabbage/cordova-wp7
Posted by pu...@apache.org.
Merge branch 'master' of github.com:purplecabbage/cordova-wp7
Project: http://git-wip-us.apache.org/repos/asf/cordova-wp7/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp7/commit/12474d14
Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp7/tree/12474d14
Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp7/diff/12474d14
Branch: refs/heads/master
Commit: 12474d148e0806d77b464cea3661c0f16376ec4a
Parents: 89bc040 b32ecd1
Author: Jesse MacFadyen <pu...@gmail.com>
Authored: Tue Jun 11 14:26:45 2013 -0700
Committer: Jesse MacFadyen <pu...@gmail.com>
Committed: Tue Jun 11 14:26:45 2013 -0700
----------------------------------------------------------------------
templates/standalone/Plugins/Contacts.cs | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------