Skip to content

Commit

Permalink
Add event manager (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
josesimoes authored Apr 3, 2019
1 parent 9ceca6e commit f9c74d1
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 3 deletions.
65 changes: 65 additions & 0 deletions source/Windows.Storage/RemovableDeviceEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright (c) 2019 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

using nanoFramework.Runtime.Events;

namespace Windows.Storage
{
/// <summary>
/// Contains argument values for Removable Devices events.
/// </summary>
public class RemovableDeviceEventArgs : EventArgs
{
private readonly string _path;
private readonly RemovableDeviceEvent _event;

internal RemovableDeviceEventArgs(string path, RemovableDeviceEvent deviceEvent)
{
_path = path;
_event = deviceEvent;
}

/// <summary>
/// The path of the Removable Device.
/// </summary>
public string Path
{
get
{
return _path;
}
}

/// <summary>
/// The <see cref="RemovableDeviceEvent"/> occurred.
/// </summary>
public RemovableDeviceEvent Event
{
get
{
return _event;
}
}

/// <summary>
/// Specifies the type of event occurred with the Removable Device specified.
/// </summary>
/// <remarks>
/// This enum is specific to nanoFramework. There is no equivalent in the UWP API.
/// </remarks>
public enum RemovableDeviceEvent
{
/// <summary>
/// A Removable Device has been inserted.
/// </summary>
Inserted,

/// <summary>
/// A Removable Device has been removed.
/// </summary>
Removed,
}
}
}
156 changes: 156 additions & 0 deletions source/Windows.Storage/StorageEventManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
//
// Copyright (c) 2019 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

using nanoFramework.Runtime.Events;
using System;
using static Windows.Storage.RemovableDeviceEventArgs;

namespace Windows.Storage
{
/// <summary>
/// Provides an event handler that is called when a Removable Device event occurs.
/// </summary>
/// <param name="sender">Specifies the object that sent the Removable Device event. </param>
/// <param name="e">Contains the Removable Device event arguments. </param>
public delegate void RemovableDeviceEventHandler(Object sender, RemovableDeviceEventArgs e);

/// <summary>
/// Event manager for Storage events.
/// </summary>
public static class StorageEventManager
{
[Flags]
internal enum StorageEventType : byte
{
Invalid = 0,
RemovableDeviceInsertion = 1,
RemovableDeviceRemoval = 2,
}

internal class StorageEvent : BaseEvent
{
public StorageEventType EventType;
public byte DriveIndex;
public DateTime Time;
}

internal class StorageEventListener : IEventListener, IEventProcessor
{
public void InitializeForEventSource()
{
}

public BaseEvent ProcessEvent(uint data1, uint data2, DateTime time)
{
StorageEvent storageEvent = new StorageEvent
{
EventType = (StorageEventType)((data1 >> 16) & 0xFF),
DriveIndex = (byte)(data1 & 0xFF),
Time = time
};

return storageEvent;
}

public bool OnEvent(BaseEvent ev)
{
if (ev is StorageEvent)
{
OnStorageEventCallback((StorageEvent)ev);
}

return true;
}
}

/// <summary>
/// Event that occurs when a Removable Device is inserted.
/// </summary>
/// <remarks>
/// The <see cref="StorageEventManager"/> class raises <see cref="RemovableDeviceEventArgs"/> events when Removable Devices (typically SD Cards and USB mass storage device) are inserted and removed.
///
/// To have a <see cref="StorageEventManager"/> object call an event-handling method when a <see cref="RemovableDeviceInserted"/> event occurs,
/// you must associate the method with a <see cref="RemovableDeviceEventHandler"/> delegate, and add this delegate to this event.
/// </remarks>
public static event RemovableDeviceEventHandler RemovableDeviceInserted;

/// <summary>
/// Event that occurs when a Removable Device is removed.
/// </summary>
/// <remarks>
/// The <see cref="StorageEventManager"/> class raises <see cref="RemovableDeviceEventArgs"/> events when Removable Devices (typically SD Cards and USB mass storage device) are inserted and removed.
///
/// To have a <see cref="StorageEventManager"/> object call an event-handling method when a <see cref="RemovableDeviceRemoved"/> event occurs,
/// you must associate the method with a <see cref="RemovableDeviceEventHandler"/> delegate, and add this delegate to this event.
/// </remarks>
public static event RemovableDeviceEventHandler RemovableDeviceRemoved;

static StorageEventManager()
{
StorageEventListener storageEventListener = new StorageEventListener();

EventSink.AddEventProcessor(EventCategory.Storage, storageEventListener);
EventSink.AddEventListener(EventCategory.Storage, storageEventListener);
}

internal static void OnStorageEventCallback(StorageEvent storageEvent)
{
switch (storageEvent.EventType)
{
case StorageEventType.RemovableDeviceInsertion:
{
if (RemovableDeviceInserted != null)
{
RemovableDeviceEventArgs args = new RemovableDeviceEventArgs(DriveIndexToPath(storageEvent.DriveIndex), RemovableDeviceEvent.Inserted);

RemovableDeviceInserted(null, args);
}
break;
}
case StorageEventType.RemovableDeviceRemoval:
{
if (RemovableDeviceRemoved != null)
{
RemovableDeviceEventArgs args = new RemovableDeviceEventArgs(DriveIndexToPath(storageEvent.DriveIndex), RemovableDeviceEvent.Removed);

RemovableDeviceRemoved(null, args);
}

break;
}
default:
{
break;
}
}
}

internal static string DriveIndexToPath(byte driveIndex)
{
/////////////////////////////////////////////////////////////////////////////////////
// Drive indexes have a fixed mapping with a driver letter
// Keep the various INDEX0_DRIVE_LETTER in sync with nanoHAL_Windows_Storage.h in native code
/////////////////////////////////////////////////////////////////////////////////////

switch (driveIndex)
{
// INDEX0_DRIVE_LETTER
case 0:
return "D:";

// INDEX1_DRIVE_LETTER
case 1:
return "E:";

// INDEX2_DRIVE_LETTER
case 2:
return "F:";

default:
throw new IndexOutOfRangeException();
}
}
}
}
12 changes: 11 additions & 1 deletion source/Windows.Storage/Windows.Storage.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
<NFMDP_PE_LoadHints Include="..\packages\nanoFramework.Windows.Storage.Streams.1.0.5-preview-009\lib\Windows.Storage.Streams.dll">
<InProject>false</InProject>
</NFMDP_PE_LoadHints>
<NFMDP_PE_LoadHints Include="..\packages\nanoFramework.Runtime.Events.1.0.5-preview-010\lib\nanoFramework.Runtime.Events.dll">
<InProject>false</InProject>
</NFMDP_PE_LoadHints>
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
Expand Down Expand Up @@ -91,6 +94,8 @@
<Compile Include="SetVersionDeferral.cs" />
<Compile Include="SetVersionRequest.cs" />
<Compile Include="StorageDeleteOption.cs" />
<Compile Include="StorageEventManager.cs" />
<Compile Include="RemovableDeviceEventArgs.cs" />
<Compile Include="StorageFile.cs" />
<Compile Include="StorageFolder.cs" />
<Compile Include="StorageItemTypes.cs" />
Expand Down Expand Up @@ -126,6 +131,11 @@
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="nanoFramework.Runtime.Events, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.Runtime.Events.1.0.5-preview-010\lib\nanoFramework.Runtime.Events.dll</HintPath>
<Private>True</Private>
<SpecificVersion>True</SpecificVersion>
</Reference>
<Reference Include="Windows.Storage.Streams, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c07d481e9758c731">
<HintPath>..\packages\nanoFramework.Windows.Storage.Streams.1.0.5-preview-009\lib\Windows.Storage.Streams.dll</HintPath>
<Private>True</Private>
Expand All @@ -144,4 +154,4 @@
</PropertyGroup>
<Error Condition="!Exists('..\packages\Nerdbank.GitVersioning.3.0.6-beta\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Nerdbank.GitVersioning.3.0.6-beta\build\Nerdbank.GitVersioning.targets'))" />
</Target>
</Project>
</Project>
1 change: 1 addition & 0 deletions source/Windows.Storage/packages.config
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.1.1" targetFramework="netnanoframework10" />
<package id="nanoFramework.Runtime.Events" version="1.0.5-preview-010" targetFramework="netnanoframework10" />
<package id="nanoFramework.Windows.Storage.Streams" version="1.0.5-preview-009" targetFramework="netnanoframework10" />
<package id="Nerdbank.GitVersioning" version="3.0.6-beta" developmentDependency="true" targetFramework="netnanoframework10" />
</packages>
11 changes: 9 additions & 2 deletions source/nanoFramework.Windows.Storage.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "AccessRemovableDevices", ".
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "FileAccess", "..\tests\FileAccess\FileAccess.nfproj", "{4BAF8D93-66CF-40C4-8B85-9F533E8558E4}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "RemovableDeviceEvent", "..\tests\RemovableDeviceEvent\RemovableDeviceEvent.nfproj", "{4464304E-8A03-4076-8605-CBB29040A88A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -19,13 +21,11 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Release|Any CPU.Build.0 = Release|Any CPU
{4AA106B9-7837-4A19-9EBC-DF2A1E164F74}.Release|Any CPU.Deploy.0 = Release|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Release|Any CPU.Build.0 = Release|Any CPU
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF}.Release|Any CPU.Deploy.0 = Release|Any CPU
Expand All @@ -35,13 +35,20 @@ Global
{4BAF8D93-66CF-40C4-8B85-9F533E8558E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4BAF8D93-66CF-40C4-8B85-9F533E8558E4}.Release|Any CPU.Build.0 = Release|Any CPU
{4BAF8D93-66CF-40C4-8B85-9F533E8558E4}.Release|Any CPU.Deploy.0 = Release|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Release|Any CPU.Build.0 = Release|Any CPU
{4464304E-8A03-4076-8605-CBB29040A88A}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{59548C76-0B49-46C7-A5E8-3A956A5B5DAF} = {6F8DD06E-3CCC-4229-8DED-5307A752094A}
{4BAF8D93-66CF-40C4-8B85-9F533E8558E4} = {6F8DD06E-3CCC-4229-8DED-5307A752094A}
{4464304E-8A03-4076-8605-CBB29040A88A} = {6F8DD06E-3CCC-4229-8DED-5307A752094A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC71AD2E-C0BC-4806-AEDF-0EC53145FD40}
Expand Down
33 changes: 33 additions & 0 deletions tests/RemovableDeviceEvent/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// Copyright (c) 2019 The nanoFramework project contributors
// See LICENSE file in the project root for full license information.
//

using System;
using System.Threading;
using Windows.Storage;

namespace RemovableDeviceEvent
{
public class Program
{
public static void Main()
{
// add event handlers for Removable Device insertion and removal
StorageEventManager.RemovableDeviceInserted += StorageEventManager_RemovableDeviceInserted;
StorageEventManager.RemovableDeviceRemoved += StorageEventManager_RemovableDeviceRemoved;

Thread.Sleep(Timeout.Infinite);
}

private static void StorageEventManager_RemovableDeviceRemoved(object sender, RemovableDeviceEventArgs e)
{
Console.WriteLine($"Removable Device @ \"{e.Path}\" removed.");
}

private static void StorageEventManager_RemovableDeviceInserted(object sender, RemovableDeviceEventArgs e)
{
Console.WriteLine($"Removable Device @ \"{e.Path}\" inserted.");
}
}
}
33 changes: 33 additions & 0 deletions tests/RemovableDeviceEvent/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharp.BlankApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharp.BlankApplication")]
[assembly: AssemblyCopyright("Copyright © ")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading

0 comments on commit f9c74d1

Please sign in to comment.