Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

sample app itself

  • Loading branch information...
commit 238516daf033960c321e7ac65e6c8a6a4e5b2649 1 parent 78a634b
authored October 27, 2011

Showing 86 changed files with 35,748 additions and 0 deletions. Show diff stats Hide diff stats

  1. 40  .gitignore
  2. 1  README
  3. BIN  framework/Images/appbar.feature.video.rest.png
  4. BIN  framework/Images/appbar.save.rest.png
  5. BIN  framework/Images/appbar.stop.rest.png
  6. 31  framework/PGView.xaml
  7. 376  framework/PGView.xaml.cs
  8. 83  framework/PhoneGap/CommandFactory.cs
  9. 307  framework/PhoneGap/Commands/Accelerometer.cs
  10. 579  framework/PhoneGap/Commands/AudioPlayer.cs
  11. 120  framework/PhoneGap/Commands/BaseCommand.cs
  12. 315  framework/PhoneGap/Commands/Camera.cs
  13. 705  framework/PhoneGap/Commands/Capture.cs
  14. 90  framework/PhoneGap/Commands/Compass.cs
  15. 84  framework/PhoneGap/Commands/Connection.cs
  16. 521  framework/PhoneGap/Commands/Contacts.cs
  17. 33  framework/PhoneGap/Commands/DebugConsole.cs
  18. 119  framework/PhoneGap/Commands/Device.cs
  19. 1,425  framework/PhoneGap/Commands/File.cs
  20. 312  framework/PhoneGap/Commands/FileTransfer.cs
  21. 445  framework/PhoneGap/Commands/Media.cs
  22. 94  framework/PhoneGap/Commands/MimeTypeMapper.cs
  23. 26  framework/PhoneGap/Commands/Motion.cs
  24. 207  framework/PhoneGap/Commands/Notification.cs
  25. 26  framework/PhoneGap/Commands/Reachability.cs
  26. 26  framework/PhoneGap/Commands/Sound.cs
  27. 131  framework/PhoneGap/DOMStorageHelper.cs
  28. 81  framework/PhoneGap/JSON/JsonHelper.cs
  29. 199  framework/PhoneGap/NativeExecution.cs
  30. 80  framework/PhoneGap/PhoneGapCommandCall.cs
  31. 156  framework/PhoneGap/PluginResult.cs
  32. 68  framework/PhoneGap/ScriptCallback.cs
  33. 100  framework/PhoneGap/UI/AudioCaptureTask.cs
  34. 48  framework/PhoneGap/UI/AudioRecorder.xaml
  35. 380  framework/PhoneGap/UI/AudioRecorder.xaml.cs
  36. 99  framework/PhoneGap/UI/VideoCaptureTask.cs
  37. 34  framework/PhoneGap/UI/VideoRecorder.xaml
  38. 400  framework/PhoneGap/UI/VideoRecorder.xaml.cs
  39. 37  framework/Properties/AssemblyInfo.cs
  40. 161  framework/WP7GapClassLib.csproj
  41. 20  framework/WP7GapClassLib.sln
  42. 208  framework/js/DOMStorage.js
  43. 147  framework/js/accelerometer.js
  44. 146  framework/js/camera.js
  45. 201  framework/js/capture.js
  46. 149  framework/js/compass.js
  47. 312  framework/js/contact.js
  48. 75  framework/js/device.js
  49. 5  framework/js/disclaimer.txt
  50. 1,041  framework/js/file.js
  51. 96  framework/js/filetransfer.js
  52. 227  framework/js/media.js
  53. 89  framework/js/network.js
  54. 128  framework/js/notification.js
  55. 3,474  framework/js/phonegap-1.1.0.js
  56. 651  framework/js/phonegap.js.base
  57. 65  framework/js/phonegap.tt
  58. BIN  framework/resources/notification-beep.wav
  59. 20  samples/People/App.xaml
  60. 149  samples/People/App.xaml.cs
  61. BIN  samples/People/ApplicationIcon.png
  62. BIN  samples/People/Background.png
  63. 35  samples/People/GapSourceDictionary.tt
  64. 17  samples/People/GapSourceDictionary.xml
  65. 27  samples/People/MainPage.xaml
  66. 33  samples/People/MainPage.xaml.cs
  67. 40  samples/People/ManifestProcessor.js
  68. 155  samples/People/People.csproj
  69. 28  samples/People/People.sln
  70. 5  samples/People/Properties/AppManifest.xml
  71. 37  samples/People/Properties/AssemblyInfo.cs
  72. 33  samples/People/Properties/WMAppManifest.xml
  73. BIN  samples/People/SplashScreenImage.jpg
  74. BIN  samples/People/www/addContacts.png
  75. 174  samples/People/www/app.logic.js
  76. BIN  samples/People/www/avatar1.jpg
  77. BIN  samples/People/www/avatar2.jpg
  78. 155  samples/People/www/index.html
  79. 9,046  samples/People/www/jquery-1.6.4.js
  80. 4  samples/People/www/jquery-1.6.4.min.js
  81. 1,843  samples/People/www/jquery.mobile-1.0rc1.css
  82. 5,095  samples/People/www/jquery.mobile-1.0rc1.js
  83. 258  samples/People/www/master.css
  84. 3,482  samples/People/www/phonegap-1.1.0.js
  85. 139  samples/People/www/search.html
  86. BIN  samples/People/www/searchContacts.png
40  .gitignore
... ...
@@ -0,0 +1,40 @@
  1
+# Shamelessly stolen from http://gist.github.com/114476
  2
+# .gitignore for .NET projects
  3
+# Thanks to Derick Bailey
  4
+# http://www.lostechies.com/blogs/derickbailey/archive/2009/05/18/a-net-c-developer-s-gitignore-file.aspx
  5
+# Additional Thanks to
  6
+# - Alexey Abramov
  7
+ 
  8
+# Standard VS.NET and ReSharper Foo
  9
+obj
  10
+bin
  11
+Bin
  12
+*.csproj.user
  13
+*ReSharper*
  14
+*resharper*
  15
+*.suo
  16
+*.cache
  17
+Thumbs.db
  18
+ARMADILLO_CACHE
  19
+ 
  20
+# Other useful stuff
  21
+*.bak
  22
+*.cache
  23
+*.log
  24
+*.swp
  25
+*.user
  26
+_compareTemp
  27
+_notes
  28
+aspnet_client
  29
+httpd.parse.errors
  30
+ 
  31
+# Office Temp Files
  32
+~$*
  33
+ 
  34
+# If you have a deploy folder
  35
+# deploy
  36
+# deploy/*
  37
+ 
  38
+# Exclude ALL DLLs? (
  39
+# *.dll
  40
+ 
1  README
... ...
@@ -0,0 +1 @@
  1
+Web version of WP7 People application (very limited, aim - demo native alike UI) 
BIN  framework/Images/appbar.feature.video.rest.png
BIN  framework/Images/appbar.save.rest.png
BIN  framework/Images/appbar.stop.rest.png
31  framework/PGView.xaml
... ...
@@ -0,0 +1,31 @@
  1
+<UserControl x:Class="WP7GapClassLib.PGView"
  2
+    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3
+    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4
+    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5
+    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6
+    mc:Ignorable="d"
  7
+    FontFamily="{StaticResource PhoneFontFamilyNormal}"
  8
+    FontSize="{StaticResource PhoneFontSizeNormal}"
  9
+    Foreground="{StaticResource PhoneForegroundBrush}"
  10
+    d:DesignHeight="480" d:DesignWidth="480" 
  11
+    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone">
  12
+    
  13
+    <Grid x:Name="LayoutRoot" Background="Transparent">
  14
+        
  15
+        <phone:WebBrowser x:Name="GapBrowser" 
  16
+                          HorizontalAlignment="Stretch"  
  17
+                          VerticalAlignment="Stretch" 
  18
+                          IsScriptEnabled="True" 
  19
+                          Foreground="White"
  20
+                          Navigated="GapBrowser_Navigated" 
  21
+                          Loaded="GapBrowser_Loaded" 
  22
+                          Unloaded="GapBrowser_Unloaded" 
  23
+                          ScriptNotify="GapBrowser_ScriptNotify" 
  24
+                          LoadCompleted="GapBrowser_LoadCompleted" 
  25
+                          Navigating="GapBrowser_Navigating" 
  26
+                          NavigationFailed="GapBrowser_NavigationFailed" IsGeolocationEnabled="True" />
  27
+        
  28
+    </Grid>
  29
+</UserControl>
  30
+
  31
+    
376  framework/PGView.xaml.cs
... ...
@@ -0,0 +1,376 @@
  1
+/*
  2
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
  3
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
  4
+ *
  5
+ * Copyright (c) 2005-2011, Nitobi Software Inc.
  6
+ * Copyright (c) 2011, Microsoft Corporation
  7
+ * Copyright (c) 2011, Sergey Grebnov.
  8
+ * Copyright (c) 2011, Jesse MacFadyen.
  9
+ */
  10
+
  11
+using System;
  12
+using System.Collections.Generic;
  13
+using System.Linq;
  14
+using System.Net;
  15
+using System.Windows;
  16
+using System.Windows.Controls;
  17
+using System.Windows.Documents;
  18
+using System.Windows.Input;
  19
+using System.Windows.Media;
  20
+using System.Windows.Media.Animation;
  21
+using System.Windows.Shapes;
  22
+using Microsoft.Phone.Controls;
  23
+using System.IO.IsolatedStorage;
  24
+using System.Windows.Resources;
  25
+using System.Windows.Interop;
  26
+using System.Runtime.Serialization.Json;
  27
+using System.IO;
  28
+using System.ComponentModel;
  29
+using System.Xml.Linq;
  30
+using WP7GapClassLib.PhoneGap.Commands;
  31
+using System.Diagnostics;
  32
+using System.Text;
  33
+using Microsoft.Xna.Framework;
  34
+using WP7GapClassLib.PhoneGap;
  35
+using System.Threading;
  36
+using Microsoft.Phone.Shell;
  37
+
  38
+
  39
+namespace WP7GapClassLib
  40
+{
  41
+    public partial class PGView : UserControl
  42
+    {
  43
+
  44
+        /// <summary>
  45
+        /// Indicates whether web control has been loaded and no additional initialization is needed.
  46
+        /// Prevents data clearing during page transitions.
  47
+        /// </summary>
  48
+        private bool IsBrowserInitialized = false;
  49
+        private bool OverrideBackButton = false;
  50
+
  51
+        /// <summary>
  52
+        /// Handles native api calls
  53
+        /// </summary>
  54
+        private NativeExecution nativeExecution;
  55
+
  56
+        protected DOMStorageHelper domStorageHelper;
  57
+
  58
+        public PGView()
  59
+        {
  60
+
  61
+            InitializeComponent();
  62
+
  63
+            if (DesignerProperties.IsInDesignTool)
  64
+            {
  65
+                return;
  66
+            }
  67
+
  68
+            StartupMode mode = PhoneApplicationService.Current.StartupMode;
  69
+            Debug.WriteLine("StartupMode mode =" + mode.ToString());
  70
+
  71
+            if (mode == StartupMode.Launch)
  72
+            {
  73
+                PhoneApplicationService service = PhoneApplicationService.Current;
  74
+                service.Activated += new EventHandler<Microsoft.Phone.Shell.ActivatedEventArgs>(AppActivated);
  75
+                service.Launching += new EventHandler<LaunchingEventArgs>(AppLaunching);
  76
+                service.Deactivated += new EventHandler<DeactivatedEventArgs>(AppDeactivated);
  77
+                service.Closing += new EventHandler<ClosingEventArgs>(AppClosing);
  78
+            }
  79
+            else
  80
+            {
  81
+
  82
+            }
  83
+
  84
+            // initializes native execution logic
  85
+            this.nativeExecution = new NativeExecution(ref this.GapBrowser);
  86
+        }
  87
+
  88
+        
  89
+
  90
+        void AppClosing(object sender, ClosingEventArgs e)
  91
+        {
  92
+            Debug.WriteLine("AppClosing");
  93
+        }
  94
+
  95
+        void AppDeactivated(object sender, DeactivatedEventArgs e)
  96
+        {
  97
+            Debug.WriteLine("AppDeactivated");
  98
+
  99
+            try
  100
+            {
  101
+                GapBrowser.InvokeScript("PhoneGapCommandResult", new string[] { "pause" });
  102
+            }
  103
+            catch (Exception)
  104
+            {
  105
+                Debug.WriteLine("Pause event error");
  106
+            } 
  107
+        }
  108
+
  109
+        void AppLaunching(object sender, LaunchingEventArgs e)
  110
+        {
  111
+            Debug.WriteLine("AppLaunching");
  112
+        }
  113
+
  114
+        void AppActivated(object sender, Microsoft.Phone.Shell.ActivatedEventArgs e)
  115
+        {
  116
+            Debug.WriteLine("AppActivated");
  117
+
  118
+            try
  119
+            {
  120
+                GapBrowser.InvokeScript("PhoneGapCommandResult", new string[] { "resume" });
  121
+            }
  122
+            catch (Exception)
  123
+            {
  124
+                Debug.WriteLine("Resume event error");
  125
+            }  
  126
+        }
  127
+
  128
+        void GapBrowser_Loaded(object sender, RoutedEventArgs e)
  129
+        {
  130
+            Thread.Sleep(500);
  131
+            if (DesignerProperties.IsInDesignTool)
  132
+            {
  133
+                return;
  134
+            }
  135
+
  136
+            // prevents refreshing web control to initial state during pages transitions
  137
+            if (this.IsBrowserInitialized) return;
  138
+
  139
+            this.domStorageHelper = new DOMStorageHelper(this.GapBrowser);
  140
+
  141
+            try
  142
+            {
  143
+
  144
+                // Before we possibly clean the ISO-Store, we need to grab our generated UUID, so we can rewrite it after.
  145
+                string deviceUUID = "";
  146
+
  147
+                using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
  148
+                {
  149
+                    try
  150
+                    {
  151
+                        IsolatedStorageFileStream fileStream = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Open, FileAccess.Read, appStorage);
  152
+
  153
+                        using (StreamReader reader = new StreamReader(fileStream))
  154
+                        {
  155
+                            deviceUUID = reader.ReadLine();
  156
+                        }
  157
+                    }
  158
+                    catch (Exception /*ex*/)
  159
+                    {
  160
+                        deviceUUID = Guid.NewGuid().ToString();
  161
+                    }
  162
+
  163
+                    Debug.WriteLine("Updating IsolatedStorage for APP:DeviceID :: " + deviceUUID);
  164
+                    // always overwrite user-iso-store if we are in debug mode.
  165
+#if DEBUG
  166
+                    appStorage.Remove();
  167
+#endif 
  168
+
  169
+                    IsolatedStorageFileStream file = new IsolatedStorageFileStream("DeviceID.txt", FileMode.Create, FileAccess.Write, appStorage);
  170
+                    using (StreamWriter writeFile = new StreamWriter(file))
  171
+                    {
  172
+                        writeFile.WriteLine(deviceUUID);
  173
+                        writeFile.Close();
  174
+                    }
  175
+   
  176
+                }
  177
+
  178
+                StreamResourceInfo streamInfo = Application.GetResourceStream(new Uri("GapSourceDictionary.xml", UriKind.Relative));
  179
+
  180
+                if (streamInfo != null)
  181
+                {
  182
+                    StreamReader sr = new StreamReader(streamInfo.Stream);
  183
+                    //This will Read Keys Collection for the xml file
  184
+
  185
+                    XDocument document = XDocument.Parse(sr.ReadToEnd());
  186
+
  187
+                    var files = from results in document.Descendants("FilePath")
  188
+                                 select new
  189
+                                 {
  190
+                                     path = (string)results.Attribute("Value")
  191
+                                 };
  192
+                    StreamResourceInfo fileResourceStreamInfo;
  193
+
  194
+
  195
+
  196
+                    using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
  197
+                    {
  198
+
  199
+                        foreach (var file in files)
  200
+                        {
  201
+                            fileResourceStreamInfo = Application.GetResourceStream(new Uri(file.path, UriKind.Relative));
  202
+
  203
+                            if (fileResourceStreamInfo != null)
  204
+                            {
  205
+                                using (BinaryReader br = new BinaryReader(fileResourceStreamInfo.Stream))
  206
+                                {
  207
+                                    byte[] data = br.ReadBytes((int)fileResourceStreamInfo.Stream.Length);
  208
+
  209
+                                    string strBaseDir = file.path.Substring(0, file.path.LastIndexOf(System.IO.Path.DirectorySeparatorChar));
  210
+                                    appStorage.CreateDirectory(strBaseDir);
  211
+
  212
+                                    // This will truncate/overwrite an existing file, or 
  213
+                                    using (IsolatedStorageFileStream outFile = appStorage.OpenFile(file.path, FileMode.Create))
  214
+                                    {
  215
+                                        Debug.WriteLine("Writing data for " + file.path + " and length = " + data.Length);
  216
+                                        using (var writer = new BinaryWriter(outFile))
  217
+                                        {
  218
+                                            writer.Write(data);
  219
+                                        }
  220
+                                    }
  221
+
  222
+                                }
  223
+                            }
  224
+                            else
  225
+                            {
  226
+                                Debug.WriteLine("Failed to write file :: " + file.path + " did you forget to add it to the project?");
  227
+                            }
  228
+                        }
  229
+                    }
  230
+                }
  231
+
  232
+                // todo: this should be a start page param passed in via a getter/setter
  233
+                // aka StartPage
  234
+
  235
+                Uri indexUri = new Uri("www/index.html", UriKind.Relative);
  236
+                this.GapBrowser.Navigate(indexUri);
  237
+
  238
+                this.IsBrowserInitialized = true;
  239
+
  240
+                AttachHardwareButtonHandlers();
  241
+
  242
+            }
  243
+            catch (Exception ex)
  244
+            {
  245
+                Debug.WriteLine("Exception in GapBrowser_Loaded :: {0}", ex.Message);
  246
+            }
  247
+        }
  248
+
  249
+        void AttachHardwareButtonHandlers()
  250
+        {
  251
+            PhoneApplicationFrame frame = Application.Current.RootVisual as PhoneApplicationFrame;
  252
+            if (frame != null)
  253
+            {
  254
+                PhoneApplicationPage page = frame.Content as PhoneApplicationPage;
  255
+
  256
+                if (page != null)
  257
+                {
  258
+                    page.BackKeyPress += new EventHandler<CancelEventArgs>(page_BackKeyPress);
  259
+                    page.OrientationChanged += new EventHandler<OrientationChangedEventArgs>(page_OrientationChanged);
  260
+                }
  261
+            }
  262
+        }
  263
+
  264
+        void page_OrientationChanged(object sender, OrientationChangedEventArgs e)
  265
+        {
  266
+            //throw new NotImplementedException();
  267
+        }
  268
+
  269
+        void page_BackKeyPress(object sender, CancelEventArgs e)
  270
+        {
  271
+            if (true)
  272
+            {
  273
+                try
  274
+                {
  275
+                    //GapBrowser.InvokeScript("PhoneGapCommandResult", new string[] { "backbutton" });
  276
+                    //e.Cancel = true;
  277
+
  278
+                    if (GapBrowser.Source.ToString().ToLowerInvariant().EndsWith("index.html"))
  279
+                    {
  280
+                        return;
  281
+                    }
  282
+
  283
+                    if (GapBrowser.Source.ToString().ToLowerInvariant().EndsWith("search.html"))
  284
+                    {
  285
+                        GapBrowser.Navigate(new Uri("www/index.html", UriKind.Relative));
  286
+                    }
  287
+                    else
  288
+                    {
  289
+                        GapBrowser.InvokeScript("eval", "history.go(-1);");
  290
+                    }
  291
+                    
  292
+                    e.Cancel = true;
  293
+                }
  294
+                catch (Exception ex)
  295
+                {
  296
+                    int i = 0;
  297
+                }
  298
+            }
  299
+        }
  300
+
  301
+        void GapBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
  302
+        {
  303
+            Debug.WriteLine("GapBrowser_LoadCompleted");
  304
+        }
  305
+
  306
+
  307
+        void GapBrowser_Navigating(object sender, NavigatingEventArgs e)
  308
+        {
  309
+            Debug.WriteLine("GapBrowser_Navigating to :: " + e.Uri.ToString());
  310
+
  311
+            // TODO: tell any running plugins to stop doing what they are doing.
  312
+            // TODO: check whitelist / blacklist
  313
+            // NOTE: Navigation can be cancelled by setting :        e.Cancel = true;
  314
+        }
  315
+
  316
+        /*
  317
+         *  This method does the work of routing commands
  318
+         *  NotifyEventArgs.Value contains a string passed from JS 
  319
+         *  If the command already exists in our map, we will just attempt to call the method(action) specified, and pass the args along
  320
+         *  Otherwise, we create a new instance of the command, add it to the map, and call it ...
  321
+         *  This method may also receive JS error messages caught by window.onerror, in any case where the commandStr does not appear to be a valid command
  322
+         *  it is simply output to the debugger output, and the method returns.
  323
+         * 
  324
+         **/
  325
+        void GapBrowser_ScriptNotify(object sender, NotifyEventArgs e)
  326
+        {
  327
+            string commandStr = e.Value;
  328
+
  329
+            // DOMStorage/Local OR DOMStorage/Session
  330
+            if (commandStr.IndexOf("DOMStorage") == 0)
  331
+            {
  332
+                this.domStorageHelper.HandleStorageCommand(commandStr);
  333
+                return;
  334
+            }
  335
+            
  336
+            PhoneGapCommandCall commandCallParams = PhoneGapCommandCall.Parse(commandStr);
  337
+
  338
+            if (commandCallParams == null)
  339
+            {
  340
+                // ERROR
  341
+                Debug.WriteLine("ScriptNotify :: " + commandStr);
  342
+                return;
  343
+            }
  344
+            else if (commandCallParams.Service == "CoreEvents")
  345
+            {
  346
+                switch (commandCallParams.Action.ToLower())
  347
+                {
  348
+                    case "overridebackbutton":
  349
+                        string[] args = PhoneGap.JSON.JsonHelper.Deserialize<string[]>(commandCallParams.Args);
  350
+                        this.OverrideBackButton = (args != null && args.Length > 0 && args[0] == "true");
  351
+                        break;
  352
+                }
  353
+                return;
  354
+            }
  355
+
  356
+            this.nativeExecution.ProcessCommand(commandCallParams);
  357
+        }
  358
+
  359
+        private void GapBrowser_Unloaded(object sender, RoutedEventArgs e)
  360
+        {
  361
+            //throw new NotImplementedException();
  362
+        }
  363
+
  364
+        private void GapBrowser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
  365
+        {
  366
+            Debug.WriteLine("GapBrowser_NavigationFailed :: " + e.Uri.ToString());
  367
+        }
  368
+
  369
+        private void GapBrowser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
  370
+        {
  371
+            Debug.WriteLine("GapBrowser_Navigated");
  372
+        }
  373
+
  374
+       
  375
+    }
  376
+}
83  framework/PhoneGap/CommandFactory.cs
... ...
@@ -0,0 +1,83 @@
  1
+/*
  2
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
  3
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
  4
+ *
  5
+ * Copyright (c) 2005-2011, Nitobi Software Inc.
  6
+ * Copyright (c) 2011, Microsoft Corporation
  7
+ */
  8
+
  9
+using System;
  10
+using System.Net;
  11
+using System.Windows;
  12
+using System.Windows.Controls;
  13
+using System.Windows.Documents;
  14
+using System.Windows.Ink;
  15
+using System.Windows.Input;
  16
+using System.Windows.Media;
  17
+using System.Windows.Media.Animation;
  18
+using System.Windows.Shapes;
  19
+using System.Collections.Generic;
  20
+using WP7GapClassLib.PhoneGap.Commands;
  21
+using System.Reflection;
  22
+
  23
+namespace WP7GapClassLib.PhoneGap
  24
+{
  25
+    /// <summary>
  26
+    /// Provides functionality to create phone gap command by name.
  27
+    /// </summary>
  28
+    public static class CommandFactory
  29
+    {
  30
+        /// <summary>
  31
+        /// Represents predefined namespace name for custom plugins
  32
+        /// </summary>
  33
+        private static readonly string CustomPlaginNamespacePrefix = "PhoneGap.Extension.Commands.";
  34
+
  35
+        /// <summary>
  36
+        /// Performance optimization allowing more faster create already known commands.
  37
+        /// </summary>
  38
+        private static Dictionary<string, Type> commandMap = new Dictionary<string, Type>();
  39
+ 
  40
+        /// <summary>
  41
+        /// Creates command using command class name. Returns null for unknown commands.
  42
+        /// </summary>
  43
+        /// <param name="service">Command class name, for example Device or Notification</param>
  44
+        /// <returns>Command class instance or null</returns>
  45
+        public static BaseCommand CreateByServiceName(string service)
  46
+        {
  47
+
  48
+            if (string.IsNullOrEmpty(service))
  49
+            {
  50
+                throw new ArgumentNullException("service", "service to create can't be null");
  51
+            }
  52
+
  53
+            if (!commandMap.ContainsKey(service))
  54
+            {
  55
+            
  56
+                Type t = Type.GetType("WP7GapClassLib.PhoneGap.Commands." + service);
  57
+
  58
+                // custom plugin could be defined in own namespace and assembly
  59
+                if (t == null)
  60
+                {
  61
+                    string serviceFullName = service.Contains(".") ? service : CustomPlaginNamespacePrefix + service;
  62
+                    
  63
+                    foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
  64
+                    {
  65
+                        // in this case service name represents full type name including namespace
  66
+                        t = a.GetType(serviceFullName);
  67
+
  68
+                        if (t != null)
  69
+                            break;
  70
+                    }
  71
+
  72
+                }
  73
+
  74
+                // unknown command
  75
+                if (t == null) return null;
  76
+
  77
+                commandMap[service] = t;
  78
+            }
  79
+
  80
+            return Activator.CreateInstance(commandMap[service]) as BaseCommand;
  81
+        }
  82
+    }
  83
+}
307  framework/PhoneGap/Commands/Accelerometer.cs
... ...
@@ -0,0 +1,307 @@
  1
+/*
  2
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
  3
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
  4
+ *
  5
+ * Copyright (c) 2005-2011, Nitobi Software Inc.
  6
+ * Copyright (c) 2011, Microsoft Corporation
  7
+ * Copyright (c) 2011, Sergey Grebnov.
  8
+ * Copyright (c) 2011, Jesse MacFadyen.
  9
+ */
  10
+
  11
+using System;
  12
+using System.Collections.Generic;
  13
+using System.Runtime.Serialization;
  14
+using System.Threading;
  15
+using Microsoft.Devices.Sensors;
  16
+
  17
+namespace WP7GapClassLib.PhoneGap.Commands
  18
+{
  19
+    /// <summary>
  20
+    /// Captures device motion in the x, y, and z direction.
  21
+    /// </summary>
  22
+    public class Accelerometer : BaseCommand
  23
+    {
  24
+        #region AccelerometerOptions class
  25
+        /// <summary>
  26
+        /// Represents Accelerometer options.
  27
+        /// </summary>
  28
+        [DataContract]
  29
+        public class AccelerometerOptions
  30
+        {
  31
+            /// <summary>
  32
+            /// How often to retrieve the Acceleration in milliseconds
  33
+            /// </summary>
  34
+            [DataMember(IsRequired = false, Name = "frequency")]
  35
+            public int Frequency { get; set; }
  36
+
  37
+            /// <summary>
  38
+            /// Watcher id
  39
+            /// </summary>
  40
+            [DataMember(IsRequired = false, Name = "id")]
  41
+            public string Id { get; set; }
  42
+
  43
+            /// <summary>
  44
+            /// Creates options object with default parameters
  45
+            /// </summary>
  46
+            public AccelerometerOptions()
  47
+            {
  48
+                this.SetDefaultValues(new StreamingContext());
  49
+            }
  50
+
  51
+            /// <summary>
  52
+            /// Initializes default values for class fields.
  53
+            /// Implemented in separate method because default constructor is not invoked during deserialization.
  54
+            /// </summary>
  55
+            /// <param name="context"></param>
  56
+            [OnDeserializing()]
  57
+            public void SetDefaultValues(StreamingContext context)
  58
+            {
  59
+                this.Frequency = 10000;
  60
+            }
  61
+        }
  62
+
  63
+        #endregion
  64
+
  65
+        #region Status codes
  66
+
  67
+        public const int Stopped = 0;
  68
+        public const int Starting = 1;
  69
+        public const int Running = 2;
  70
+        public const int ErrorFailedToStart = 3;
  71
+
  72
+        #endregion
  73
+
  74
+        #region Static members
  75
+
  76
+        /// <summary>
  77
+        /// Status of listener
  78
+        /// </summary>
  79
+        private static int currentStatus;
  80
+
  81
+        /// <summary>
  82
+        /// Id for get getAcceleration method
  83
+        /// </summary>
  84
+        private static string getAccelId = "getAccelId";
  85
+
  86
+        /// <summary>
  87
+        /// Accelerometer
  88
+        /// </summary>
  89
+        private static Microsoft.Devices.Sensors.Accelerometer accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
  90
+
  91
+        /// <summary>
  92
+        /// Listeners for callbacks
  93
+        /// </summary>
  94
+        private static Dictionary<string, Accelerometer> watchers = new Dictionary<string, Accelerometer>();
  95
+
  96
+        #endregion
  97
+
  98
+        /// <summary>
  99
+        /// Time the value was last changed
  100
+        /// </summary>
  101
+        private DateTime lastValueChangedTime;
  102
+
  103
+        /// <summary>
  104
+        /// Accelerometer options
  105
+        /// </summary>
  106
+        private AccelerometerOptions accelOptions;
  107
+
  108
+        /// <summary>
  109
+        /// Start listening for acceleration sensor
  110
+        /// </summary>
  111
+        public void startWatch(string options)
  112
+        {
  113
+            try
  114
+            {
  115
+                accelOptions = JSON.JsonHelper.Deserialize<AccelerometerOptions>(options);
  116
+            }
  117
+            catch (Exception ex)
  118
+            {
  119
+                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
  120
+                return;
  121
+            }
  122
+
  123
+            if (string.IsNullOrEmpty(accelOptions.Id))
  124
+            {
  125
+                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
  126
+                return;
  127
+            }
  128
+
  129
+            try
  130
+            {
  131
+                lock (accelerometer)
  132
+                {
  133
+                    watchers.Add(accelOptions.Id, this);
  134
+                    accelerometer.CurrentValueChanged += watchers[accelOptions.Id].accelerometer_CurrentValueChanged;
  135
+                    accelerometer.Start();
  136
+                    this.SetStatus(Starting);
  137
+                }
  138
+            }
  139
+            catch (Exception e)
  140
+            {
  141
+                this.DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
  142
+                return;
  143
+            }
  144
+        }
  145
+
  146
+        /// <summary>
  147
+        /// Stops listening to acceleration sensor
  148
+        /// </summary>
  149
+        public void stopWatch(string options)
  150
+        {
  151
+            try
  152
+            {
  153
+                accelOptions = JSON.JsonHelper.Deserialize<AccelerometerOptions>(options);
  154
+            }
  155
+            catch (Exception ex)
  156
+            {
  157
+                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION, ex.Message));
  158
+                return;
  159
+            }
  160
+
  161
+            if (string.IsNullOrEmpty(accelOptions.Id))
  162
+            {
  163
+                this.DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
  164
+                return;
  165
+            }
  166
+
  167
+            if (currentStatus != Stopped)
  168
+            {
  169
+                lock (accelerometer)
  170
+                {
  171
+                    Accelerometer watcher = watchers[accelOptions.Id];
  172
+                    
  173
+                    watcher.Dispose();
  174
+                    accelerometer.CurrentValueChanged -= watcher.accelerometer_CurrentValueChanged;
  175
+                    watchers.Remove(accelOptions.Id);
  176
+                }
  177
+            }
  178
+            this.SetStatus(Stopped);
  179
+
  180
+            this.DispatchCommandResult();
  181
+        }
  182
+
  183
+        /// <summary>
  184
+        /// Gets current accelerometer coordinates
  185
+        /// </summary>
  186
+        public void getAcceleration(string options)
  187
+        {
  188
+            try
  189
+            {
  190
+                if (currentStatus != Running)
  191
+                {
  192
+                    int status = this.start();
  193
+                    if (status == ErrorFailedToStart)
  194
+                    {
  195
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
  196
+                        return;
  197
+                    }
  198
+
  199
+                    long timeout = 2000;
  200
+                    while ((currentStatus == Starting) && (timeout > 0))
  201
+                    {
  202
+                        timeout = timeout - 100;
  203
+                        Thread.Sleep(100);
  204
+                    }
  205
+
  206
+                    if (currentStatus != Running)
  207
+                    {
  208
+                        DispatchCommandResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, ErrorFailedToStart));
  209
+                        return;
  210
+                    }
  211
+                }
  212
+                lock (accelerometer)
  213
+                {
  214
+                    if (watchers.ContainsKey(getAccelId))
  215
+                    {
  216
+                        accelerometer.CurrentValueChanged -= watchers[getAccelId].accelerometer_CurrentValueChanged;
  217
+                        watchers.Remove(getAccelId);
  218
+                    }
  219
+                    DispatchCommandResult(new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted()));
  220
+                }
  221
+            }
  222
+            catch (UnauthorizedAccessException e)
  223
+            {
  224
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ILLEGAL_ACCESS_EXCEPTION, ErrorFailedToStart));
  225
+            }
  226
+            catch (Exception e)
  227
+            {
  228
+                DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ErrorFailedToStart));
  229
+            }
  230
+        }
  231
+
  232
+        /// <summary>
  233
+        /// Sensor listener event
  234
+        /// </summary>        
  235
+        private void accelerometer_CurrentValueChanged(object sender, SensorReadingEventArgs<AccelerometerReading> e)
  236
+        {
  237
+            this.SetStatus(Running);
  238
+
  239
+            if (accelOptions != null)
  240
+            {
  241
+                if (((DateTime.Now - lastValueChangedTime).TotalMilliseconds) > accelOptions.Frequency)
  242
+                {
  243
+                    lastValueChangedTime = DateTime.Now;
  244
+                    PluginResult result = new PluginResult(PluginResult.Status.OK, GetCurrentAccelerationFormatted());
  245
+                    result.KeepCallback = true;
  246
+                    DispatchCommandResult(result);
  247
+                }
  248
+            }
  249
+
  250
+            if (watchers.Count == 0)
  251
+            {
  252
+                accelerometer.Stop();
  253
+                this.SetStatus(Stopped);
  254
+            }
  255
+        }
  256
+
  257
+        /// <summary>
  258
+        /// Starts listening for acceleration sensor
  259
+        /// </summary>
  260
+        /// <returns>status of listener</returns>
  261
+        private int start()
  262
+        {
  263
+            if ((currentStatus == Running) || (currentStatus == Starting))
  264
+            {
  265
+                return currentStatus;
  266
+            }
  267
+            try
  268
+            {
  269
+                lock (accelerometer)
  270
+                {
  271
+                    watchers.Add(getAccelId, this);
  272
+                    accelerometer.CurrentValueChanged += watchers[getAccelId].accelerometer_CurrentValueChanged;
  273
+                    accelerometer.Start();
  274
+                    this.SetStatus(Starting);
  275
+                }
  276
+            }
  277
+            catch (Exception e)
  278
+            {
  279
+                this.SetStatus(ErrorFailedToStart);
  280
+            }
  281
+            return currentStatus;
  282
+        }
  283
+
  284
+        /// <summary>
  285
+        /// Formats current coordinates into JSON format
  286
+        /// </summary>
  287
+        /// <returns>Coordinates in JSON format</returns>
  288
+        private string GetCurrentAccelerationFormatted()
  289
+        {
  290
+            string resultCoordinates = String.Format("\"x\":{0},\"y\":{1},\"z\":{2}",
  291
+                            accelerometer.CurrentValue.Acceleration.X.ToString("0.00000"),
  292
+                            accelerometer.CurrentValue.Acceleration.Y.ToString("0.00000"),
  293
+                            accelerometer.CurrentValue.Acceleration.Z.ToString("0.00000"));
  294
+            resultCoordinates = "{" + resultCoordinates + "}";
  295
+            return resultCoordinates;
  296
+        }
  297
+
  298
+        /// <summary>
  299
+        /// Sets current status
  300
+        /// </summary>
  301
+        /// <param name="status">current status</param>
  302
+        private void SetStatus(int status)
  303
+        {
  304
+            currentStatus = status;
  305
+        }
  306
+    }
  307
+}
579  framework/PhoneGap/Commands/AudioPlayer.cs
... ...
@@ -0,0 +1,579 @@
  1
+/*
  2
+ * PhoneGap is available under *either* the terms of the modified BSD license *or* the
  3
+ * MIT License (2008). See http://opensource.org/licenses/alphabetical for full text.
  4
+ *
  5
+ * Copyright (c) 2005-2011, Nitobi Software Inc.
  6
+ * Copyright (c) 2011, Microsoft Corporation
  7
+ * Copyright (c) 2011, Sergey Grebnov.
  8
+ */
  9
+
  10
+using System;
  11
+using System.IO;
  12
+using System.IO.IsolatedStorage;
  13
+using System.Windows;
  14
+using System.Windows.Controls;
  15
+using System.Windows.Threading;
  16
+using Microsoft.Xna.Framework;
  17
+using Microsoft.Xna.Framework.Audio;
  18
+using Microsoft.Xna.Framework.Media;
  19
+
  20
+namespace WP7GapClassLib.PhoneGap.Commands
  21
+{    
  22
+    /// <summary>
  23
+    /// Implements audio record and play back functionality.
  24
+    /// </summary>
  25
+    internal class AudioPlayer: IDisposable
  26
+    {
  27
+        #region Constants
  28
+        
  29
+        // AudioPlayer states
  30
+        private const int MediaNone = 0;
  31
+        private const int MediaStarting = 1;
  32
+        private const int MediaRunning = 2;
  33
+        private const int MediaPaused = 3;
  34
+        private const int MediaStopped = 4;
  35
+                           
  36
+        // AudioPlayer messages
  37
+        private const int MediaState = 1;
  38
+        private const int MediaDuration = 2;
  39
+        private const int MediaPosition = 3;
  40
+        private const int MediaError = 9;
  41
+
  42
+        // AudioPlayer errors
  43
+        private const int MediaErrorPlayModeSet = 1;
  44
+        private const int MediaErrorAlreadyRecording = 2;
  45
+        private const int MediaErrorStartingRecording = 3;
  46
+        private const int MediaErrorRecordModeSet = 4;
  47
+        private const int MediaErrorStartingPlayback = 5;
  48
+        private const int MediaErrorResumeState = 6;
  49
+        private const int MediaErrorPauseState = 7;
  50
+        private const int MediaErrorStopState = 8;
  51
+
  52
+        private const string CallbackFunction = "PhoneGapMediaonStatus";
  53
+
  54
+        #endregion
  55
+
  56
+        /// <summary>
  57
+        /// The AudioHandler object
  58
+        /// </summary>
  59
+        private Media handler;					
  60
+        
  61
+        /// <summary>
  62
+        /// Temporary buffer to store audio chunk
  63
+        /// </summary>
  64
+        private byte[] buffer;
  65
+
  66
+        /// <summary>
  67
+        /// Xna game loop dispatcher
  68
+        /// </summary>
  69
+        DispatcherTimer dtXna;
  70
+
  71
+        /// <summary>
  72
+        /// Output buffer
  73
+        /// </summary>
  74
+        private MemoryStream memoryStream;
  75
+
  76
+        /// <summary>
  77
+        /// The id of this player (used to identify Media object in JavaScript)
  78
+        /// </summary>
  79
+        private String id;								
  80
+        
  81
+        /// <summary>
  82
+        /// State of recording or playback
  83
+        /// </summary>
  84
+        private int state = MediaNone;					
  85
+        
  86
+        /// <summary>
  87
+        /// File name to play or record to
  88
+        /// </summary>
  89
+        private String audioFile = null;				
  90
+        
  91
+        /// <summary>
  92
+        /// Duration of audio
  93
+        /// </summary>
  94
+        private double duration = -1;								
  95
+
  96
+        /// <summary>
  97
+        /// Audio player object
  98
+        /// </summary>
  99
+        private MediaElement player = null;
  100
+
  101
+        /// <summary>
  102
+        /// Audio source
  103
+        /// </summary>
  104
+        private Microphone recorder;
  105
+        
  106
+        /// <summary>
  107
+        /// Internal flag specified that we should only open audio w/o playing it
  108
+        /// </summary>
  109
+        private bool prepareOnly = false;
  110
+
  111
+        /// <summary>
  112
+        /// Creates AudioPlayer instance
  113
+        /// </summary>
  114
+        /// <param name="handler">Media object</param>
  115
+        /// <param name="id">player id</param>
  116
+        public AudioPlayer(Media handler, String id)
  117
+        {
  118
+            this.handler = handler;
  119
+            this.id = id;
  120
+        }	
  121
+
  122
+        /// <summary>
  123
+        /// Destroys player and stop audio playing or recording
  124
+        /// </summary>
  125
+        public void Dispose()
  126
+        {
  127
+            if (this.player != null)
  128
+            {
  129
+                this.stopPlaying();
  130
+                this.player = null;
  131
+            }
  132
+            if (this.recorder != null)
  133
+            {
  134
+                this.stopRecording();
  135
+                this.recorder = null;
  136
+            }
  137
+
  138
+            this.FinalizeXnaGameLoop();
  139
+        }
  140
+
  141
+        /// <summary>
  142
+        /// Starts recording, data is stored in memory
  143
+        /// </summary>
  144
+        /// <param name="filePath"></param>
  145
+        public void startRecording(string filePath)
  146
+        {
  147
+            if (this.player != null)
  148
+            {
  149
+                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorPlayModeSet));
  150
+            }
  151
+            else if (this.recorder == null)
  152
+            {
  153
+                try
  154
+                {
  155
+                        this.audioFile = filePath;
  156
+                        this.InitializeXnaGameLoop();
  157
+                        this.recorder = Microphone.Default;
  158
+                        this.recorder.BufferDuration = TimeSpan.FromMilliseconds(500);
  159
+                        this.buffer = new byte[recorder.GetSampleSizeInBytes(this.recorder.BufferDuration)];
  160
+                        this.recorder.BufferReady += new EventHandler<EventArgs>(recorderBufferReady);
  161
+                        this.memoryStream = new MemoryStream();
  162
+                        this.WriteWavHeader(this.memoryStream, this.recorder.SampleRate);
  163
+                        this.recorder.Start();
  164
+                        FrameworkDispatcher.Update();
  165
+                        this.SetState(MediaRunning);
  166
+                }
  167
+                catch (Exception e)
  168
+                {
  169
+                        this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorStartingRecording));
  170
+                }
  171
+            } else 
  172
+            {
  173
+
  174
+                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorAlreadyRecording));
  175
+            }
  176
+        }
  177
+
  178
+        /// <summary>
  179
+        /// Stops recording
  180
+        /// </summary>
  181
+        public void stopRecording()
  182
+        {
  183
+            if (this.recorder != null)
  184
+            { 
  185
+                if (this.state == MediaRunning)
  186
+                {
  187
+                    try
  188
+                    {
  189
+                        this.recorder.Stop();
  190
+                        this.recorder.BufferReady -= recorderBufferReady;
  191
+                        this.recorder = null;
  192
+                        SaveAudioClipToLocalStorage();
  193
+                        this.FinalizeXnaGameLoop();
  194
+                        this.SetState(MediaStopped);
  195
+                    }
  196
+                    catch (Exception e)
  197
+                    {                
  198
+                        //TODO 
  199
+                    }
  200
+                }
  201
+            }
  202
+        }
  203
+        
  204
+        /// <summary>
  205
+        /// Starts or resume playing audio file
  206
+        /// </summary>
  207
+        /// <param name="filePath">The name of the audio file</param>
  208
+        /// <summary>
  209
+        /// Starts or resume playing audio file
  210
+        /// </summary>
  211
+        /// <param name="filePath">The name of the audio file</param>
  212
+        public void startPlaying(string filePath)
  213
+        {
  214
+            if (this.recorder != null)
  215
+            {
  216
+                this.handler.InvokeCustomScript(new ScriptCallback(CallbackFunction, this.id, MediaError, MediaErrorRecordModeSet));
  217
+                return;
  218
+            }
  219
+
  220
+
  221
+            if ((this.player == null) || (this.state == MediaStopped))
  222
+            {
  223
+                try
  224
+                {
  225
+                    if (this.player == null)
  226
+                    {
  227
+
  228
+                        if (!Application.Current.Resources.Contains("PhoneGapMediaPlayer"))
  229
+                        {
  230
+                            throw new Exception("PhoneGapMediaPlayer wasn't found in application resources");
  231