Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B67BACE1C for ; Wed, 19 Jun 2013 00:17:44 +0000 (UTC) Received: (qmail 19336 invoked by uid 500); 19 Jun 2013 00:17:43 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 19252 invoked by uid 500); 19 Jun 2013 00:17:43 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 18693 invoked by uid 99); 19 Jun 2013 00:17:43 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 19 Jun 2013 00:17:43 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id DA0BB8A7DB9; Wed, 19 Jun 2013 00:17:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: purplecabbage@apache.org To: commits@cordova.apache.org Date: Wed, 19 Jun 2013 00:17:54 -0000 Message-Id: <5c6d8dff4b9f4d18bf58b4dd7775aaa9@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [13/50] [abbrv] git commit: plugin code becomes common code plugin code becomes common code Project: http://git-wip-us.apache.org/repos/asf/cordova-wp8/repo Commit: http://git-wip-us.apache.org/repos/asf/cordova-wp8/commit/dec32ea1 Tree: http://git-wip-us.apache.org/repos/asf/cordova-wp8/tree/dec32ea1 Diff: http://git-wip-us.apache.org/repos/asf/cordova-wp8/diff/dec32ea1 Branch: refs/heads/2.9.x Commit: dec32ea1dacf831b74704ddd8dccf173e08d69b8 Parents: df40aaf Author: Jesse MacFadyen Authored: Tue Jun 18 12:21:21 2013 -0700 Committer: Jesse MacFadyen Committed: Tue Jun 18 12:21:21 2013 -0700 ---------------------------------------------------------------------- wp7/template/Plugins/Accelerometer.cs | 196 -- wp7/template/Plugins/AudioFormatsHelper.cs | 89 - wp7/template/Plugins/AudioPlayer.cs | 620 ------- wp7/template/Plugins/Battery.cs | 79 - wp7/template/Plugins/Camera.cs | 490 ----- wp7/template/Plugins/Capture.cs | 736 -------- wp7/template/Plugins/Compass.cs | 362 ---- wp7/template/Plugins/Contacts.cs | 664 ------- wp7/template/Plugins/DebugConsole.cs | 49 - wp7/template/Plugins/Device.cs | 135 -- wp7/template/Plugins/File.cs | 1676 ------------------ wp7/template/Plugins/FileTransfer.cs | 526 ------ wp7/template/Plugins/GeoLocation.cs | 34 - wp7/template/Plugins/Globalization.cs | 1177 ------------ wp7/template/Plugins/ImageExifHelper.cs | 209 --- wp7/template/Plugins/InAppBrowser.cs | 271 --- wp7/template/Plugins/Media.cs | 547 ------ wp7/template/Plugins/MimeTypeMapper.cs | 101 -- wp7/template/Plugins/NetworkStatus.cs | 129 -- wp7/template/Plugins/Notification.cs | 361 ---- wp7/template/Plugins/UI/AudioCaptureTask.cs | 107 -- wp7/template/Plugins/UI/AudioRecorder.xaml | 66 - wp7/template/Plugins/UI/AudioRecorder.xaml.cs | 307 ---- wp7/template/Plugins/UI/ImageCapture.xaml | 26 - wp7/template/Plugins/UI/ImageCapture.xaml.cs | 109 -- wp7/template/Plugins/UI/NotificationBox.xaml | 62 - wp7/template/Plugins/UI/NotificationBox.xaml.cs | 41 - wp7/template/Plugins/UI/VideoCaptureTask.cs | 105 -- wp7/template/Plugins/UI/VideoRecorder.xaml | 52 - wp7/template/Plugins/UI/VideoRecorder.xaml.cs | 405 ----- wp8/template/Plugins/Accelerometer.cs | 196 -- wp8/template/Plugins/AudioFormatsHelper.cs | 89 - wp8/template/Plugins/AudioPlayer.cs | 620 ------- wp8/template/Plugins/Battery.cs | 79 - wp8/template/Plugins/Camera.cs | 490 ----- wp8/template/Plugins/Capture.cs | 736 -------- wp8/template/Plugins/Compass.cs | 362 ---- wp8/template/Plugins/Contacts.cs | 664 ------- wp8/template/Plugins/DebugConsole.cs | 49 - wp8/template/Plugins/Device.cs | 135 -- wp8/template/Plugins/File.cs | 1676 ------------------ wp8/template/Plugins/FileTransfer.cs | 526 ------ wp8/template/Plugins/GeoLocation.cs | 34 - wp8/template/Plugins/Globalization.cs | 1177 ------------ wp8/template/Plugins/ImageExifHelper.cs | 209 --- wp8/template/Plugins/InAppBrowser.cs | 271 --- wp8/template/Plugins/Media.cs | 547 ------ wp8/template/Plugins/MimeTypeMapper.cs | 101 -- wp8/template/Plugins/NetworkStatus.cs | 129 -- wp8/template/Plugins/Notification.cs | 361 ---- wp8/template/Plugins/UI/AudioCaptureTask.cs | 107 -- wp8/template/Plugins/UI/AudioRecorder.xaml | 66 - wp8/template/Plugins/UI/AudioRecorder.xaml.cs | 307 ---- wp8/template/Plugins/UI/ImageCapture.xaml | 26 - wp8/template/Plugins/UI/ImageCapture.xaml.cs | 109 -- wp8/template/Plugins/UI/NotificationBox.xaml | 62 - wp8/template/Plugins/UI/NotificationBox.xaml.cs | 41 - wp8/template/Plugins/UI/VideoCaptureTask.cs | 105 -- wp8/template/Plugins/UI/VideoRecorder.xaml | 52 - wp8/template/Plugins/UI/VideoRecorder.xaml.cs | 405 ----- wp8/template/VERSION | 1 - wp8/template/www/index.html | 2 +- wp8/tooling/scripts/createTemplates.js | 1 - 63 files changed, 1 insertion(+), 19465 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/Accelerometer.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/Accelerometer.cs b/wp7/template/Plugins/Accelerometer.cs deleted file mode 100644 index cba911c..0000000 --- a/wp7/template/Plugins/Accelerometer.cs +++ /dev/null @@ -1,196 +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.Collections.Generic; -using System.Runtime.Serialization; -using System.Threading; -using Microsoft.Devices.Sensors; -using System.Globalization; -using System.Diagnostics; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Captures device motion in the x, y, and z direction. - /// - public class Accelerometer : BaseCommand - { - #region AccelerometerOptions class - /// - /// Represents Accelerometer options. - /// - [DataContract] - public class AccelerometerOptions - { - /// - /// How often to retrieve the Acceleration in milliseconds - /// - [DataMember(IsRequired = false, Name = "frequency")] - public int Frequency { get; set; } - - /// - /// Watcher id - /// - [DataMember(IsRequired = false, Name = "id")] - public string Id { get; set; } - - /// - /// Creates options object with default parameters - /// - public AccelerometerOptions() - { - this.SetDefaultValues(new StreamingContext()); - } - - /// - /// Initializes default values for class fields. - /// Implemented in separate method because default constructor is not invoked during deserialization. - /// - /// - [OnDeserializing()] - public void SetDefaultValues(StreamingContext context) - { - this.Frequency = 10000; - } - } - - #endregion - - #region Status codes and Constants - - public const int Stopped = 0; - public const int Starting = 1; - public const int Running = 2; - public const int ErrorFailedToStart = 3; - - public const double gConstant = -9.81; - - #endregion - - #region Static members - - /// - /// Status of listener - /// - private static int currentStatus; - - /// - /// Accelerometer - /// - private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer(); - - private static DateTime StartOfEpoch = new DateTime(1970, 1, 1, 0, 0, 0); - - #endregion - - /// - /// Sensor listener event - /// - private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs e) - { - this.SetStatus(Running); - - PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted()); - result.KeepCallback = true; - DispatchCommandResult(result); - } - - /// - /// Starts listening for acceleration sensor - /// - /// status of listener - public void start(string options) - { - if ((currentStatus == Running) || (currentStatus == Starting)) - { - return; - } - try - { - lock (accelerometer) - { - accelerometer.CurrentValueChanged += accelerometer_CurrentValueChanged; - accelerometer.Start(); - this.SetStatus(Starting); - } - - long timeout = 2000; - while ((currentStatus == Starting) && (timeout > 0)) - { - timeout = timeout - 100; - Thread.Sleep(100); - } - - if (currentStatus != Running) - { - this.SetStatus(ErrorFailedToStart); - DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart)); - return; - } - } - catch (Exception) - { - this.SetStatus(ErrorFailedToStart); - DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart)); - return; - } - PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT); - result.KeepCallback = true; - DispatchCommandResult(result); - } - - public void stop(string options) - { - if (currentStatus == Running) - { - lock (accelerometer) - { - accelerometer.CurrentValueChanged -= accelerometer_CurrentValueChanged; - accelerometer.Stop(); - this.SetStatus(Stopped); - } - } - DispatchCommandResult(new PluginResult(PluginResult.Status.OK)); - } - - /// - /// Formats current coordinates into JSON format - /// - /// Coordinates in JSON format - private string GetCurrentAccelerationFormatted() - { - // convert to unix timestamp - // long timestamp = ((accelerometer.CurrentValue.Timestamp.DateTime - StartOfEpoch).Ticks) / 10000; - // Note: Removed timestamp, to let the JS side create it using (new Date().getTime()) -jm - // this resolves an issue with inconsistencies between JS dates and Native DateTime - string resultCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}", - (accelerometer.CurrentValue.Acceleration.X * gConstant).ToString("0.00000", CultureInfo.InvariantCulture), - (accelerometer.CurrentValue.Acceleration.Y * gConstant).ToString("0.00000", CultureInfo.InvariantCulture), - (accelerometer.CurrentValue.Acceleration.Z * gConstant).ToString("0.00000", CultureInfo.InvariantCulture)); - return "{" + resultCoordinates + "}"; - } - - /// - /// Sets current status - /// - /// current status - private void SetStatus(int status) - { - currentStatus = status; - } - } -} - http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/AudioFormatsHelper.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/AudioFormatsHelper.cs b/wp7/template/Plugins/AudioFormatsHelper.cs deleted file mode 100644 index dca7ee6..0000000 --- a/wp7/template/Plugins/AudioFormatsHelper.cs +++ /dev/null @@ -1,89 +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.IO; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Provides extra functionality to support different audio formats. - /// - public static class AudioFormatsHelper - { - #region Wav - /// - /// Adds wav file format header to the stream - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// The stream - /// Sample Rate - public static void InitializeWavStream(this Stream stream, int sampleRate) - { - #region args checking - - if (stream == null) - { - throw new ArgumentNullException("stream can't be null or empty"); - } - - #endregion - - int numBits = 16; - int numBytes = numBits / 8; - - 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(sampleRate), 0, 4); - stream.Write(BitConverter.GetBytes(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); - } - - /// - /// Updates wav file format header - /// https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ - /// - /// Wav stream - public static void UpdateWavStream(this Stream stream) - { - #region args checking - - if (stream == null) - { - throw new ArgumentNullException("stream can't be null or empty"); - } - - #endregion - - var position = stream.Position; - - stream.Seek(4, SeekOrigin.Begin); - stream.Write(BitConverter.GetBytes((int)stream.Length - 8), 0, 4); - stream.Seek(40, SeekOrigin.Begin); - stream.Write(BitConverter.GetBytes((int)stream.Length - 44), 0, 4); - stream.Seek(position, SeekOrigin.Begin); - } - - #endregion - } -} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/AudioPlayer.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/AudioPlayer.cs b/wp7/template/Plugins/AudioPlayer.cs deleted file mode 100644 index a83be5b..0000000 --- a/wp7/template/Plugins/AudioPlayer.cs +++ /dev/null @@ -1,620 +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.IO; -using System.IO.IsolatedStorage; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Threading; -using Microsoft.Xna.Framework; -using Microsoft.Xna.Framework.Audio; -using Microsoft.Xna.Framework.Media; -using Microsoft.Phone.Controls; -using System.Diagnostics; -using System.Windows.Resources; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Implements audio record and play back functionality. - /// - internal class AudioPlayer : IDisposable - { - #region Constants - - // AudioPlayer states - private const int PlayerState_None = 0; - private const int PlayerState_Starting = 1; - private const int PlayerState_Running = 2; - private const int PlayerState_Paused = 3; - private const int PlayerState_Stopped = 4; - - // AudioPlayer messages - private const int MediaState = 1; - private const int MediaDuration = 2; - private const int MediaPosition = 3; - private const int MediaError = 9; - - // AudioPlayer errors - private const int MediaErrorPlayModeSet = 1; - private const int MediaErrorAlreadyRecording = 2; - private const int MediaErrorStartingRecording = 3; - private const int MediaErrorRecordModeSet = 4; - private const int MediaErrorStartingPlayback = 5; - private const int MediaErrorResumeState = 6; - private const int MediaErrorPauseState = 7; - private const int MediaErrorStopState = 8; - - //TODO: get rid of this callback, it should be universal - //private const string CallbackFunction = "CordovaMediaonStatus"; - - #endregion - - /// - /// The AudioHandler object - /// - private Media handler; - - /// - /// Temporary buffer to store audio chunk - /// - private byte[] buffer; - - /// - /// Xna game loop dispatcher - /// - DispatcherTimer dtXna; - - /// - /// Output buffer - /// - private MemoryStream memoryStream; - - /// - /// The id of this player (used to identify Media object in JavaScript) - /// - private String id; - - /// - /// State of recording or playback - /// - private int state = PlayerState_None; - - /// - /// File name to play or record to - /// - private String audioFile = null; - - /// - /// Duration of audio - /// - private double duration = -1; - - /// - /// Audio player object - /// - private MediaElement player = null; - - /// - /// Audio source - /// - private Microphone recorder; - - /// - /// Internal flag specified that we should only open audio w/o playing it - /// - private bool prepareOnly = false; - - /// - /// Creates AudioPlayer instance - /// - /// Media object - /// player id - public AudioPlayer(Media handler, String id) - { - this.handler = handler; - this.id = id; - } - - /// - /// Destroys player and stop audio playing or recording - /// - public void Dispose() - { - if (this.player != null) - { - this.stopPlaying(); - this.player = null; - } - if (this.recorder != null) - { - this.stopRecording(); - this.recorder = null; - } - - this.FinalizeXnaGameLoop(); - } - - private void InvokeCallback(int message, string value, bool removeHandler) - { - string args = string.Format("('{0}',{1},{2});", this.id, message, value); - string callback = @"(function(id,msg,value){ - try { - if (msg == Media.MEDIA_ERROR) { - value = {'code':value}; - } - Media.onStatus(id,msg,value); - } - catch(e) { - console.log('Error calling Media.onStatus :: ' + e); - } - })" + args; - this.handler.InvokeCustomScript(new ScriptCallback("eval", new string[] { callback }), false); - } - - private void InvokeCallback(int message, int value, bool removeHandler) - { - InvokeCallback(message, value.ToString(), removeHandler); - } - - private void InvokeCallback(int message, double value, bool removeHandler) - { - InvokeCallback(message, value.ToString(), removeHandler); - } - - /// - /// Starts recording, data is stored in memory - /// - /// - public void startRecording(string filePath) - { - if (this.player != null) - { - InvokeCallback(MediaError, MediaErrorPlayModeSet, false); - } - else if (this.recorder == null) - { - try - { - this.audioFile = filePath; - this.InitializeXnaGameLoop(); - this.recorder = Microphone.Default; - this.recorder.BufferDuration = TimeSpan.FromMilliseconds(500); - this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)]; - this.recorder.BufferReady += new EventHandler(recorderBufferReady); - this.memoryStream = new MemoryStream(); - this.memoryStream.InitializeWavStream(this.recorder.SampleRate); - this.recorder.Start(); - FrameworkDispatcher.Update(); - this.SetState(PlayerState_Running); - } - catch (Exception) - { - InvokeCallback(MediaError, MediaErrorStartingRecording, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingRecording),false); - } - } - else - { - InvokeCallback(MediaError, MediaErrorAlreadyRecording, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorAlreadyRecording),false); - } - } - - /// - /// Stops recording - /// - public void stopRecording() - { - if (this.recorder != null) - { - if (this.state == PlayerState_Running) - { - try - { - this.recorder.Stop(); - this.recorder.BufferReady -= recorderBufferReady; - this.recorder = null; - SaveAudioClipToLocalStorage(); - this.FinalizeXnaGameLoop(); - this.SetState(PlayerState_Stopped); - } - catch (Exception) - { - //TODO - } - } - } - } - - /// - /// Starts or resume playing audio file - /// - /// The name of the audio file - /// - /// Starts or resume playing audio file - /// - /// The name of the audio file - public void startPlaying(string filePath) - { - if (this.recorder != null) - { - InvokeCallback(MediaError, MediaErrorRecordModeSet, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorRecordModeSet),false); - return; - } - - - if (this.player == null || this.player.Source.AbsolutePath.LastIndexOf(filePath) < 0) - { - try - { - // this.player is a MediaElement, it must be added to the visual tree in order to play - PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame; - if (frame != null) - { - PhoneApplicationPage page = frame.Content as PhoneApplicationPage; - if (page != null) - { - Grid grid = page.FindName("LayoutRoot") as Grid; - if (grid != null) - { - - this.player = grid.FindName("playerMediaElement") as MediaElement; - if (this.player == null) // still null ? - { - this.player = new MediaElement(); - this.player.Name = "playerMediaElement"; - grid.Children.Add(this.player); - this.player.Visibility = Visibility.Visible; - } - if (this.player.CurrentState == System.Windows.Media.MediaElementState.Playing) - { - this.player.Stop(); // stop it! - } - - this.player.Source = null; // Garbage collect it. - this.player.MediaOpened += MediaOpened; - this.player.MediaEnded += MediaEnded; - this.player.MediaFailed += MediaFailed; - } - } - } - - this.audioFile = filePath; - - Uri uri = new Uri(filePath, UriKind.RelativeOrAbsolute); - if (uri.IsAbsoluteUri) - { - this.player.Source = uri; - } - else - { - using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication()) - { - if (!isoFile.FileExists(filePath)) - { - // try to unpack it from the dll into isolated storage - StreamResourceInfo fileResourceStreamInfo = Application.GetResourceStream(new Uri(filePath, UriKind.Relative)); - if (fileResourceStreamInfo != null) - { - using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream)) - { - byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length); - - string[] dirParts = filePath.Split('/'); - string dirName = ""; - for (int n = 0; n < dirParts.Length - 1; n++) - { - dirName += dirParts[n] + "/"; - } - if (!isoFile.DirectoryExists(dirName)) - { - isoFile.CreateDirectory(dirName); - } - - using (IsolatedStorageFileStream outFile = isoFile.OpenFile(filePath, FileMode.Create)) - { - using (BinaryWriter writer = new BinaryWriter(outFile)) - { - writer.Write(data); - } - } - } - } - } - if (isoFile.FileExists(filePath)) - { - using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, isoFile)) - { - this.player.SetSource(stream); - } - } - else - { - InvokeCallback(MediaError, MediaErrorPlayModeSet, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, 1), false); - return; - } - } - } - this.SetState(PlayerState_Starting); - } - catch (Exception e) - { - Debug.WriteLine("Error in AudioPlayer::startPlaying : " + e.Message); - InvokeCallback(MediaError, MediaErrorStartingPlayback, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingPlayback),false); - } - } - else - { - if (this.state != PlayerState_Running) - { - this.player.Play(); - this.SetState(PlayerState_Running); - } - else - { - InvokeCallback(MediaError, MediaErrorResumeState, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorResumeState),false); - } - } - } - - /// - /// Callback to be invoked when the media source is ready for playback - /// - private void MediaOpened(object sender, RoutedEventArgs arg) - { - if (this.player != null) - { - this.duration = this.player.NaturalDuration.TimeSpan.TotalSeconds; - InvokeCallback(MediaDuration, this.duration, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaDuration, this.duration),false); - if (!this.prepareOnly) - { - this.player.Play(); - this.SetState(PlayerState_Running); - } - this.prepareOnly = false; - } - else - { - // TODO: occasionally MediaOpened is signalled, but player is null - } - } - - /// - /// Callback to be invoked when playback of a media source has completed - /// - private void MediaEnded(object sender, RoutedEventArgs arg) - { - this.SetState(PlayerState_Stopped); - } - - /// - /// Callback to be invoked when playback of a media source has failed - /// - private void MediaFailed(object sender, RoutedEventArgs arg) - { - player.Stop(); - InvokeCallback(MediaError, MediaErrorStartingPlayback, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError.ToString(), "Media failed"),false); - } - - /// - /// Seek or jump to a new time in the track - /// - /// The new track position - public void seekToPlaying(int milliseconds) - { - if (this.player != null) - { - TimeSpan tsPos = new TimeSpan(0, 0, 0, 0, milliseconds); - this.player.Position = tsPos; - InvokeCallback(MediaPosition, milliseconds / 1000.0f, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, milliseconds / 1000.0f),false); - } - } - - /// - /// Set the volume of the player - /// - /// volume 0.0-1.0, default value is 0.5 - public void setVolume(double vol) - { - if (this.player != null) - { - this.player.Volume = vol; - } - } - - /// - /// Pauses playing - /// - public void pausePlaying() - { - if (this.state == PlayerState_Running) - { - this.player.Pause(); - this.SetState(PlayerState_Paused); - } - else - { - InvokeCallback(MediaError, MediaErrorPauseState, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPauseState),false); - } - } - - - /// - /// Stops playing the audio file - /// - public void stopPlaying() - { - if ((this.state == PlayerState_Running) || (this.state == PlayerState_Paused)) - { - this.player.Stop(); - - this.player.Position = new TimeSpan(0L); - this.SetState(PlayerState_Stopped); - } - //else // Why is it an error to call stop on a stopped media? - //{ - // this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStopState), false); - //} - } - - /// - /// Gets current position of playback - /// - /// current position - public double getCurrentPosition() - { - if ((this.state == PlayerState_Running) || (this.state == PlayerState_Paused)) - { - double currentPosition = this.player.Position.TotalSeconds; - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaPosition, currentPosition),false); - return currentPosition; - } - else - { - return 0; - } - } - - /// - /// Gets the duration of the audio file - /// - /// The name of the audio file - /// track duration - public double getDuration(string filePath) - { - if (this.recorder != null) - { - return (-2); - } - - if (this.player != null) - { - return this.duration; - - } - else - { - this.prepareOnly = true; - this.startPlaying(filePath); - return this.duration; - } - } - - /// - /// Sets the state and send it to JavaScript - /// - /// state - private void SetState(int state) - { - if (this.state != state) - { - InvokeCallback(MediaState, state, false); - //this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaState, state),false); - } - - this.state = state; - } - - #region record methods - - /// - /// Copies data from recorder to memory storages and updates recording state - /// - /// - /// - private void recorderBufferReady(object sender, EventArgs e) - { - this.recorder.GetData(this.buffer); - this.memoryStream.Write(this.buffer, 0, this.buffer.Length); - } - - /// - /// Writes audio data from memory to isolated storage - /// - /// - private void SaveAudioClipToLocalStorage() - { - if (this.memoryStream == null || this.memoryStream.Length <= 0) - { - return; - } - - this.memoryStream.UpdateWavStream(); - - try - { - using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication()) - { - string directory = Path.GetDirectoryName(audioFile); - - if (!isoFile.DirectoryExists(directory)) - { - isoFile.CreateDirectory(directory); - } - - this.memoryStream.Seek(0, SeekOrigin.Begin); - - using (IsolatedStorageFileStream fileStream = isoFile.CreateFile(audioFile)) - { - this.memoryStream.CopyTo(fileStream); - } - } - } - catch (Exception) - { - //TODO: log or do something else - throw; - } - } - - #region Xna loop - /// - /// Special initialization required for the microphone: XNA game loop - /// - private void InitializeXnaGameLoop() - { - // Timer to simulate the XNA game loop (Microphone is from XNA) - this.dtXna = new DispatcherTimer(); - this.dtXna.Interval = TimeSpan.FromMilliseconds(33); - this.dtXna.Tick += delegate { try { FrameworkDispatcher.Update(); } catch { } }; - this.dtXna.Start(); - } - /// - /// Finalizes XNA game loop for microphone - /// - private void FinalizeXnaGameLoop() - { - // Timer to simulate the XNA game loop (Microphone is from XNA) - if (this.dtXna != null) - { - this.dtXna.Stop(); - this.dtXna = null; - } - } - - #endregion - - #endregion - } -} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/Battery.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/Battery.cs b/wp7/template/Plugins/Battery.cs deleted file mode 100644 index 962959e..0000000 --- a/wp7/template/Plugins/Battery.cs +++ /dev/null @@ -1,79 +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.Net; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows.Ink; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using System.Windows.Shapes; - -using Microsoft.Phone.Info; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Listens for changes to the state of the battery on the device. - /// Currently only the "isPlugged" parameter available via native APIs. - /// - public class Battery : BaseCommand - { - private bool isPlugged = false; - private EventHandler powerChanged; - - public Battery() - { - powerChanged = new EventHandler(DeviceStatus_PowerSourceChanged); - isPlugged = DeviceStatus.PowerSource.ToString().CompareTo("External") == 0; - } - - public void start(string options) - { - // Register power changed event handler - DeviceStatus.PowerSourceChanged += powerChanged; - - PluginResult result = new PluginResult(PluginResult.Status.NO_RESULT); - result.KeepCallback = true; - DispatchCommandResult(result); - } - public void stop(string options) - { - // Unregister power changed event handler - DeviceStatus.PowerSourceChanged -= powerChanged; - } - - private void DeviceStatus_PowerSourceChanged(object sender, EventArgs e) - { - isPlugged = DeviceStatus.PowerSource.ToString().CompareTo("External") == 0; - PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentBatteryStateFormatted()); - result.KeepCallback = true; - DispatchCommandResult(result); - } - - private string GetCurrentBatteryStateFormatted() - { - string batteryState = String.Format("\"level\":{0},\"isPlugged\":{1}", - "null", - isPlugged ? "true" : "false" - ); - batteryState = "{" + batteryState + "}"; - return batteryState; - } - - } -} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/Camera.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/Camera.cs b/wp7/template/Plugins/Camera.cs deleted file mode 100644 index 5ff8045..0000000 --- a/wp7/template/Plugins/Camera.cs +++ /dev/null @@ -1,490 +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.Net; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Documents; -using System.Windows.Ink; -using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Animation; -using System.Collections.Generic; -using Microsoft.Phone.Tasks; -using System.Runtime.Serialization; -using System.IO; -using System.IO.IsolatedStorage; -using System.Windows.Media.Imaging; -using Microsoft.Phone; -using Microsoft.Xna.Framework.Media; -using System.Diagnostics; - -namespace WPCordovaClassLib.Cordova.Commands -{ - public class Camera : BaseCommand - { - - /// - /// Return base64 encoded string - /// - private const int DATA_URL = 0; - - /// - /// Return file uri - /// - private const int FILE_URI = 1; - - /// - /// Choose image from picture library - /// - private const int PHOTOLIBRARY = 0; - - /// - /// Take picture from camera - /// - - private const int CAMERA = 1; - - /// - /// Choose image from picture library - /// - private const int SAVEDPHOTOALBUM = 2; - - /// - /// Take a picture of type JPEG - /// - private const int JPEG = 0; - - /// - /// Take a picture of type PNG - /// - private const int PNG = 1; - - /// - /// Folder to store captured images - /// - private const string isoFolder = "CapturedImagesCache"; - - /// - /// Represents captureImage action options. - /// - [DataContract] - public class CameraOptions - { - /// - /// Source to getPicture from. - /// - [DataMember(IsRequired = false, Name = "sourceType")] - public int PictureSourceType { get; set; } - - /// - /// Format of image that returned from getPicture. - /// - [DataMember(IsRequired = false, Name = "destinationType")] - public int DestinationType { get; set; } - - /// - /// Quality of saved image - /// - [DataMember(IsRequired = false, Name = "quality")] - public int Quality { get; set; } - - /// - /// Controls whether or not the image is also added to the device photo album. - /// - [DataMember(IsRequired = false, Name = "saveToPhotoAlbum")] - public bool SaveToPhotoAlbum { get; set; } - - /// - /// Ignored - /// - [DataMember(IsRequired = false, Name = "correctOrientation")] - public bool CorrectOrientation { get; set; } - - - - /// - /// Ignored - /// - [DataMember(IsRequired = false, Name = "allowEdit")] - public bool AllowEdit { get; set; } - - /// - /// Height in pixels to scale image - /// - [DataMember(IsRequired = false, Name = "encodingType")] - public int EncodingType { get; set; } - - /// - /// Height in pixels to scale image - /// - [DataMember(IsRequired = false, Name = "mediaType")] - public int MediaType { get; set; } - - - /// - /// Height in pixels to scale image - /// - [DataMember(IsRequired = false, Name = "targetHeight")] - public int TargetHeight { get; set; } - - - /// - /// Width in pixels to scale image - /// - [DataMember(IsRequired = false, Name = "targetWidth")] - public int TargetWidth { get; set; } - - /// - /// Creates options object with default parameters - /// - public CameraOptions() - { - this.SetDefaultValues(new StreamingContext()); - } - - /// - /// Initializes default values for class fields. - /// Implemented in separate method because default constructor is not invoked during deserialization. - /// - /// - [OnDeserializing()] - public void SetDefaultValues(StreamingContext context) - { - PictureSourceType = CAMERA; - DestinationType = FILE_URI; - Quality = 80; - TargetHeight = -1; - TargetWidth = -1; - SaveToPhotoAlbum = false; - CorrectOrientation = true; - AllowEdit = false; - MediaType = -1; - EncodingType = -1; - } - } - - /// - /// Used to open photo library - /// - PhotoChooserTask photoChooserTask; - - /// - /// Used to open camera application - /// - CameraCaptureTask cameraTask; - - /// - /// Camera options - /// - CameraOptions cameraOptions; - - public void takePicture(string options) - { - try - { - string[] args = JSON.JsonHelper.Deserialize(options); - // ["quality", "destinationType", "sourceType", "targetWidth", "targetHeight", "encodingType", - // "mediaType", "allowEdit", "correctOrientation", "saveToPhotoAlbum" ] - this.cameraOptions = new CameraOptions(); - this.cameraOptions.Quality = int.Parse(args[0]); - this.cameraOptions.DestinationType = int.Parse(args[1]); - this.cameraOptions.PictureSourceType = int.Parse(args[2]); - this.cameraOptions.TargetWidth = int.Parse(args[3]); - this.cameraOptions.TargetHeight = int.Parse(args[4]); - this.cameraOptions.EncodingType = int.Parse(args[5]); - this.cameraOptions.MediaType = int.Parse(args[6]); - this.cameraOptions.AllowEdit = bool.Parse(args[7]); - this.cameraOptions.CorrectOrientation = bool.Parse(args[8]); - this.cameraOptions.SaveToPhotoAlbum = bool.Parse(args[9]); - - //this.cameraOptions = String.IsNullOrEmpty(options) ? - // new CameraOptions() : JSON.JsonHelper.Deserialize(options); - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - //TODO Check if all the options are acceptable - - - if (cameraOptions.PictureSourceType == CAMERA) - { - cameraTask = new CameraCaptureTask(); - cameraTask.Completed += onCameraTaskCompleted; - cameraTask.Show(); - } - else - { - if ((cameraOptions.PictureSourceType == PHOTOLIBRARY) || (cameraOptions.PictureSourceType == SAVEDPHOTOALBUM)) - { - photoChooserTask = new PhotoChooserTask(); - photoChooserTask.Completed += onPickerTaskCompleted; - photoChooserTask.Show(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT)); - } - } - - } - - public void onCameraTaskCompleted(object sender, PhotoResult e) - { - if (e.Error != null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - return; - } - - switch (e.TaskResult) - { - case TaskResult.OK: - try - { - string imagePathOrContent = string.Empty; - - if (cameraOptions.DestinationType == FILE_URI) - { - // Save image in media library - if (cameraOptions.SaveToPhotoAlbum) - { - MediaLibrary library = new MediaLibrary(); - Picture pict = library.SavePicture(e.OriginalFileName, e.ChosenPhoto); // to save to photo-roll ... - } - - int orient = ImageExifHelper.getImageOrientationFromStream(e.ChosenPhoto); - int newAngle = 0; - switch (orient) - { - case ImageExifOrientation.LandscapeLeft: - newAngle = 90; - break; - case ImageExifOrientation.PortraitUpsideDown: - newAngle = 180; - break; - case ImageExifOrientation.LandscapeRight: - newAngle = 270; - break; - case ImageExifOrientation.Portrait: - default: break; // 0 default already set - } - - Stream rotImageStream = ImageExifHelper.RotateStream(e.ChosenPhoto, newAngle); - - // we should return stream position back after saving stream to media library - rotImageStream.Seek(0, SeekOrigin.Begin); - - WriteableBitmap image = PictureDecoder.DecodeJpeg(rotImageStream); - - imagePathOrContent = this.SaveImageToLocalStorage(image, Path.GetFileName(e.OriginalFileName)); - - - } - else if (cameraOptions.DestinationType == DATA_URL) - { - imagePathOrContent = this.GetImageContent(e.ChosenPhoto); - } - else - { - // TODO: shouldn't this happen before we launch the camera-picker? - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType")); - return; - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, imagePathOrContent)); - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error retrieving image.")); - } - break; - - case TaskResult.Cancel: - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection cancelled.")); - break; - - default: - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection did not complete!")); - break; - } - - } - - public void onPickerTaskCompleted(object sender, PhotoResult e) - { - if (e.Error != null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - return; - } - - switch (e.TaskResult) - { - case TaskResult.OK: - try - { - string imagePathOrContent = string.Empty; - - if (cameraOptions.DestinationType == FILE_URI) - { - WriteableBitmap image = PictureDecoder.DecodeJpeg(e.ChosenPhoto); - imagePathOrContent = this.SaveImageToLocalStorage(image, Path.GetFileName(e.OriginalFileName)); - } - else if (cameraOptions.DestinationType == DATA_URL) - { - imagePathOrContent = this.GetImageContent(e.ChosenPhoto); - - } - else - { - // TODO: shouldn't this happen before we launch the camera-picker? - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Incorrect option: destinationType")); - return; - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, imagePathOrContent)); - - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error retrieving image.")); - } - break; - - case TaskResult.Cancel: - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection cancelled.")); - break; - - default: - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Selection did not complete!")); - break; - } - } - - /// - /// Returns image content in a form of base64 string - /// - /// Image stream - /// Base64 representation of the image - private string GetImageContent(Stream stream) - { - int streamLength = (int)stream.Length; - byte[] fileData = new byte[streamLength + 1]; - stream.Read(fileData, 0, streamLength); - - //use photo's actual width & height if user doesn't provide width & height - if (cameraOptions.TargetWidth < 0 && cameraOptions.TargetHeight < 0) - { - stream.Close(); - return Convert.ToBase64String(fileData); - } - else - { - // resize photo - byte[] resizedFile = ResizePhoto(stream, fileData); - stream.Close(); - return Convert.ToBase64String(resizedFile); - } - } - - /// - /// Resize image - /// - /// Image stream - /// File data - /// resized image - private byte[] ResizePhoto(Stream stream, byte[] fileData) - { - int streamLength = (int)stream.Length; - int intResult = 0; - - byte[] resizedFile; - - stream.Read(fileData, 0, streamLength); - - BitmapImage objBitmap = new BitmapImage(); - MemoryStream objBitmapStream = new MemoryStream(fileData); - MemoryStream objBitmapStreamResized = new MemoryStream(); - WriteableBitmap objWB; - objBitmap.SetSource(stream); - objWB = new WriteableBitmap(objBitmap); - - // resize the photo with user defined TargetWidth & TargetHeight - Extensions.SaveJpeg(objWB, objBitmapStreamResized, cameraOptions.TargetWidth, cameraOptions.TargetHeight, 0, cameraOptions.Quality); - - //Convert the resized stream to a byte array. - streamLength = (int)objBitmapStreamResized.Length; - resizedFile = new Byte[streamLength]; //-1 - objBitmapStreamResized.Position = 0; - //for some reason we have to set Position to zero, but we don't have to earlier when we get the bytes from the chosen photo... - intResult = objBitmapStreamResized.Read(resizedFile, 0, streamLength); - - return resizedFile; - } - - /// - /// Saves captured image in isolated storage - /// - /// image file name - /// Image path - private string SaveImageToLocalStorage(WriteableBitmap image, string imageFileName) - { - - if (image == null) - { - throw new ArgumentNullException("imageBytes"); - } - try - { - - - var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); - - if (!isoFile.DirectoryExists(isoFolder)) - { - isoFile.CreateDirectory(isoFolder); - } - - string filePath = System.IO.Path.Combine("///" + isoFolder + "/", imageFileName); - - using (var stream = isoFile.CreateFile(filePath)) - { - // resize image if Height and Width defined via options - if (cameraOptions.TargetHeight > 0 && cameraOptions.TargetWidth > 0) - { - image.SaveJpeg(stream, cameraOptions.TargetWidth, cameraOptions.TargetHeight, 0, cameraOptions.Quality); - } - else - { - image.SaveJpeg(stream, image.PixelWidth, image.PixelHeight, 0, cameraOptions.Quality); - } - } - - return new Uri(filePath, UriKind.Relative).ToString(); - } - catch (Exception) - { - //TODO: log or do something else - throw; - } - } - - } -} http://git-wip-us.apache.org/repos/asf/cordova-wp8/blob/dec32ea1/wp7/template/Plugins/Capture.cs ---------------------------------------------------------------------- diff --git a/wp7/template/Plugins/Capture.cs b/wp7/template/Plugins/Capture.cs deleted file mode 100644 index 5e14a16..0000000 --- a/wp7/template/Plugins/Capture.cs +++ /dev/null @@ -1,736 +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.Collections.Generic; -using System.IO; -using System.IO.IsolatedStorage; -using System.Runtime.Serialization; -using System.Windows.Media.Imaging; -using Microsoft.Phone; -using Microsoft.Phone.Tasks; -using Microsoft.Xna.Framework.Media; -using WPCordovaClassLib.Cordova.UI; -using AudioResult = WPCordovaClassLib.Cordova.UI.AudioCaptureTask.AudioResult; -using VideoResult = WPCordovaClassLib.Cordova.UI.VideoCaptureTask.VideoResult; -using System.Windows; -using System.Diagnostics; -using Microsoft.Phone.Controls; - -namespace WPCordovaClassLib.Cordova.Commands -{ - /// - /// Provides access to the audio, image, and video capture capabilities of the device - /// - public class Capture : BaseCommand - { - #region Internal classes (options and resultant objects) - - /// - /// Represents captureImage action options. - /// - [DataContract] - public class CaptureImageOptions - { - /// - /// The maximum number of images the device user can capture in a single capture operation. The value must be greater than or equal to 1 (defaults to 1). - /// - [DataMember(IsRequired = false, Name = "limit")] - public int Limit { get; set; } - - public static CaptureImageOptions Default - { - get { return new CaptureImageOptions() { Limit = 1 }; } - } - } - - /// - /// Represents captureAudio action options. - /// - [DataContract] - public class CaptureAudioOptions - { - /// - /// The maximum number of audio files the device user can capture in a single capture operation. The value must be greater than or equal to 1 (defaults to 1). - /// - [DataMember(IsRequired = false, Name = "limit")] - public int Limit { get; set; } - - public static CaptureAudioOptions Default - { - get { return new CaptureAudioOptions() { Limit = 1 }; } - } - } - - /// - /// Represents captureVideo action options. - /// - [DataContract] - public class CaptureVideoOptions - { - /// - /// The maximum number of video files the device user can capture in a single capture operation. The value must be greater than or equal to 1 (defaults to 1). - /// - [DataMember(IsRequired = false, Name = "limit")] - public int Limit { get; set; } - - public static CaptureVideoOptions Default - { - get { return new CaptureVideoOptions() { Limit = 1 }; } - } - } - - /// - /// Represents getFormatData action options. - /// - [DataContract] - public class MediaFormatOptions - { - /// - /// File path - /// - [DataMember(IsRequired = true, Name = "fullPath")] - public string FullPath { get; set; } - - /// - /// File mime type - /// - [DataMember(Name = "type")] - public string Type { get; set; } - - } - - /// - /// Stores image info - /// - [DataContract] - public class MediaFile - { - - [DataMember(Name = "name")] - public string FileName { get; set; } - - [DataMember(Name = "fullPath")] - public string FilePath { get; set; } - - [DataMember(Name = "type")] - public string Type { get; set; } - - [DataMember(Name = "lastModifiedDate")] - public string LastModifiedDate { get; set; } - - [DataMember(Name = "size")] - public long Size { get; set; } - - public MediaFile(string filePath, Picture image) - { - this.FilePath = filePath; - this.FileName = System.IO.Path.GetFileName(this.FilePath); - this.Type = MimeTypeMapper.GetMimeType(FileName); - this.Size = image.GetImage().Length; - - using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) - { - this.LastModifiedDate = storage.GetLastWriteTime(filePath).DateTime.ToString(); - } - - } - - public MediaFile(string filePath, Stream stream) - { - this.FilePath = filePath; - this.FileName = System.IO.Path.GetFileName(this.FilePath); - this.Type = MimeTypeMapper.GetMimeType(FileName); - this.Size = stream.Length; - - using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication()) - { - this.LastModifiedDate = storage.GetLastWriteTime(filePath).DateTime.ToString(); - } - } - } - - /// - /// Stores additional media file data - /// - [DataContract] - public class MediaFileData - { - [DataMember(Name = "height")] - public int Height { get; set; } - - [DataMember(Name = "width")] - public int Width { get; set; } - - [DataMember(Name = "bitrate")] - public int Bitrate { get; set; } - - [DataMember(Name = "duration")] - public int Duration { get; set; } - - [DataMember(Name = "codecs")] - public string Codecs { get; set; } - - public MediaFileData(WriteableBitmap image) - { - this.Height = image.PixelHeight; - this.Width = image.PixelWidth; - this.Bitrate = 0; - this.Duration = 0; - this.Codecs = ""; - } - } - - #endregion - - /// - /// Folder to store captured images - /// - private string isoFolder = "CapturedImagesCache"; - - /// - /// Capture Image options - /// - protected CaptureImageOptions captureImageOptions; - - /// - /// Capture Audio options - /// - protected CaptureAudioOptions captureAudioOptions; - - /// - /// Capture Video options - /// - protected CaptureVideoOptions captureVideoOptions; - - /// - /// Used to open camera application - /// - private CameraCaptureTask cameraTask; - - /// - /// Used for audio recording - /// - private AudioCaptureTask audioCaptureTask; - - /// - /// Used for video recording - /// - private VideoCaptureTask videoCaptureTask; - - /// - /// Stores information about captured files - /// - List files = new List(); - - /// - /// Launches default camera application to capture image - /// - /// may contains limit or mode parameters - public void captureImage(string options) - { - try - { - try - { - - string args = JSON.JsonHelper.Deserialize(options)[0]; - this.captureImageOptions = String.IsNullOrEmpty(args) ? CaptureImageOptions.Default : JSON.JsonHelper.Deserialize(args); - - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - - cameraTask = new CameraCaptureTask(); - cameraTask.Completed += this.cameraTask_Completed; - cameraTask.Show(); - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message)); - } - } - - /// - /// Launches our own audio recording control to capture audio - /// - /// may contains additional parameters - public void captureAudio(string options) - { - try - { - try - { - string args = JSON.JsonHelper.Deserialize(options)[0]; - this.captureAudioOptions = String.IsNullOrEmpty(args) ? CaptureAudioOptions.Default : JSON.JsonHelper.Deserialize(args); - - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - audioCaptureTask = new AudioCaptureTask(); - audioCaptureTask.Completed += audioRecordingTask_Completed; - audioCaptureTask.Show(); - - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message)); - } - } - - /// - /// Launches our own video recording control to capture video - /// - /// may contains additional parameters - public void captureVideo(string options) - { - try - { - try - { - string args = JSON.JsonHelper.Deserialize(options)[0]; - this.captureVideoOptions = String.IsNullOrEmpty(args) ? CaptureVideoOptions.Default : JSON.JsonHelper.Deserialize(args); - - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - videoCaptureTask = new VideoCaptureTask(); - videoCaptureTask.Completed += videoRecordingTask_Completed; - videoCaptureTask.Show(); - - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message)); - } - } - - /// - /// Retrieves the format information of the media file. - /// - /// - public void getFormatData(string options) - { - try - { - MediaFormatOptions mediaFormatOptions; - try - { - mediaFormatOptions = new MediaFormatOptions(); - string[] optionStrings = JSON.JsonHelper.Deserialize(options); - mediaFormatOptions.FullPath = optionStrings[0]; - mediaFormatOptions.Type = optionStrings[1]; - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - if (string.IsNullOrEmpty(mediaFormatOptions.FullPath)) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION)); - } - - string mimeType = mediaFormatOptions.Type; - - if (string.IsNullOrEmpty(mimeType)) - { - mimeType = MimeTypeMapper.GetMimeType(mediaFormatOptions.FullPath); - } - - if (mimeType.Equals("image/jpeg")) - { - Deployment.Current.Dispatcher.BeginInvoke(() => - { - WriteableBitmap image = ExtractImageFromLocalStorage(mediaFormatOptions.FullPath); - - if (image == null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "File not found")); - return; - } - - MediaFileData mediaData = new MediaFileData(image); - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, mediaData)); - }); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - } - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - } - } - - /// - /// Opens specified file in media player - /// - /// MediaFile to play - public void play(string options) - { - try - { - MediaFile file; - - try - { - file = String.IsNullOrEmpty(options) ? null : JSON.JsonHelper.Deserialize(options)[0]; - - } - catch (Exception ex) - { - this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message)); - return; - } - - if (file == null || String.IsNullOrEmpty(file.FilePath)) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "File path is missing")); - return; - } - - // if url starts with '/' media player throws FileNotFound exception - Uri fileUri = new Uri(file.FilePath.TrimStart(new char[] { '/', '\\' }), UriKind.Relative); - - MediaPlayerLauncher player = new MediaPlayerLauncher(); - player.Media = fileUri; - player.Location = MediaLocationType.Data; - player.Show(); - - this.DispatchCommandResult(new PluginResult(PluginResult.Status.OK)); - - } - catch (Exception e) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, e.Message)); - } - } - - - /// - /// Handles result of capture to save image information - /// - /// - /// stores information about current captured image - private void cameraTask_Completed(object sender, PhotoResult e) - { - - if (e.Error != null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - return; - } - - switch (e.TaskResult) - { - case TaskResult.OK: - try - { - string fileName = System.IO.Path.GetFileName(e.OriginalFileName); - - // Save image in media library - MediaLibrary library = new MediaLibrary(); - Picture image = library.SavePicture(fileName, e.ChosenPhoto); - - int orient = ImageExifHelper.getImageOrientationFromStream(e.ChosenPhoto); - int newAngle = 0; - switch (orient) - { - case ImageExifOrientation.LandscapeLeft: - newAngle = 90; - break; - case ImageExifOrientation.PortraitUpsideDown: - newAngle = 180; - break; - case ImageExifOrientation.LandscapeRight: - newAngle = 270; - break; - case ImageExifOrientation.Portrait: - default: break; // 0 default already set - } - - Stream rotImageStream = ImageExifHelper.RotateStream(e.ChosenPhoto, newAngle); - - // Save image in isolated storage - - // we should return stream position back after saving stream to media library - rotImageStream.Seek(0, SeekOrigin.Begin); - - byte[] imageBytes = new byte[rotImageStream.Length]; - rotImageStream.Read(imageBytes, 0, imageBytes.Length); - rotImageStream.Dispose(); - string pathLocalStorage = this.SaveImageToLocalStorage(fileName, isoFolder, imageBytes); - imageBytes = null; - // Get image data - MediaFile data = new MediaFile(pathLocalStorage, image); - - this.files.Add(data); - - if (files.Count < this.captureImageOptions.Limit) - { - cameraTask.Show(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error capturing image.")); - } - break; - - case TaskResult.Cancel: - if (files.Count > 0) - { - // User canceled operation, but some images were made - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Canceled.")); - } - break; - - default: - if (files.Count > 0) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Did not complete!")); - } - break; - } - } - - /// - /// Handles result of audio recording tasks - /// - /// - /// stores information about current captured audio - private void audioRecordingTask_Completed(object sender, AudioResult e) - { - - if (e.Error != null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - return; - } - - switch (e.TaskResult) - { - case TaskResult.OK: - try - { - // Get image data - MediaFile data = new MediaFile(e.AudioFileName, e.AudioFile); - - this.files.Add(data); - - if (files.Count < this.captureAudioOptions.Limit) - { - audioCaptureTask.Show(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error capturing audio.")); - } - break; - - case TaskResult.Cancel: - if (files.Count > 0) - { - // User canceled operation, but some audio clips were made - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Canceled.")); - } - break; - - default: - if (files.Count > 0) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Did not complete!")); - } - break; - } - } - - /// - /// Handles result of video recording tasks - /// - /// - /// stores information about current captured video - private void videoRecordingTask_Completed(object sender, VideoResult e) - { - - if (e.Error != null) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR)); - return; - } - - switch (e.TaskResult) - { - case TaskResult.OK: - try - { - // Get image data - MediaFile data = new MediaFile(e.VideoFileName, e.VideoFile); - - this.files.Add(data); - - if (files.Count < this.captureVideoOptions.Limit) - { - videoCaptureTask.Show(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - } - catch (Exception) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Error capturing video.")); - } - break; - - case TaskResult.Cancel: - if (files.Count > 0) - { - // User canceled operation, but some video clips were made - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Canceled.")); - } - break; - - default: - if (files.Count > 0) - { - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, files)); - files.Clear(); - } - else - { - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Did not complete!")); - } - break; - } - } - - /// - /// Extract file from Isolated Storage as WriteableBitmap object - /// - /// - /// - private WriteableBitmap ExtractImageFromLocalStorage(string filePath) - { - try - { - - var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); - - using (var imageStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read)) - { - var imageSource = PictureDecoder.DecodeJpeg(imageStream); - return imageSource; - } - } - catch (Exception) - { - return null; - } - } - - - /// - /// Saves captured image in isolated storage - /// - /// image file name - /// folder to store images - /// Image path - private string SaveImageToLocalStorage(string imageFileName, string imageFolder, byte[] imageBytes) - { - if (imageBytes == null) - { - throw new ArgumentNullException("imageBytes"); - } - try - { - var isoFile = IsolatedStorageFile.GetUserStoreForApplication(); - - if (!isoFile.DirectoryExists(imageFolder)) - { - isoFile.CreateDirectory(imageFolder); - } - string filePath = System.IO.Path.Combine("/" + imageFolder + "/", imageFileName); - - using (IsolatedStorageFileStream stream = isoFile.CreateFile(filePath)) - { - stream.Write(imageBytes, 0, imageBytes.Length); - } - - return filePath; - } - catch (Exception) - { - //TODO: log or do something else - throw; - } - } - - - } -} \ No newline at end of file