GUI initial work (WIP)

This commit is contained in:
Tadas Baltrusaitis 2016-05-20 16:48:43 -04:00
parent 668588500c
commit e6e547b0a1
134 changed files with 32611 additions and 15 deletions

6
.gitignore vendored
View file

@ -20,3 +20,9 @@ matlab_runners/Feature Point Experiments/yt_features/
matlab_runners/Feature Point Experiments/yt_features_clm/ matlab_runners/Feature Point Experiments/yt_features_clm/
matlab_runners/Gaze Experiments/mpii_out/ matlab_runners/Gaze Experiments/mpii_out/
build/ build/
Debug/
Release/AU_predictors/
Release/
ipch/
matlab_runners/Demos/output_features_seq/
matlab_runners/Demos/output_features_vid/

View file

@ -13,7 +13,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FeatureExtraction", "exe\Fe
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{99FEBA13-BDDF-4076-B57E-D8EF4076E20D}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Libraries", "Libraries", "{99FEBA13-BDDF-4076-B57E-D8EF4076E20D}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Executables", "Executables", "{9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Command line Executables", "Command line Executables", "{9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FaceLandmarkVidMulti", "exe\FaceLandmarkVidMulti\FaceLandmarkVidMulti.vcxproj", "{C3FAF36F-44BC-4454-87C2-C5106575FE50}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FaceLandmarkVidMulti", "exe\FaceLandmarkVidMulti\FaceLandmarkVidMulti.vcxproj", "{C3FAF36F-44BC-4454-87C2-C5106575FE50}"
EndProject EndProject
@ -23,6 +23,16 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FaceLandmarkVid", "exe\Face
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FaceLandmarkImg", "exe\FaceLandmarkImg\FaceLandmarkImg.vcxproj", "{DDC3535E-526C-44EC-9DF4-739E2D3A323B}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FaceLandmarkImg", "exe\FaceLandmarkImg\FaceLandmarkImg.vcxproj", "{DDC3535E-526C-44EC-9DF4-739E2D3A323B}"
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GUI", "GUI", "{C9D8D0B0-11EC-41CB-8524-2DDB5BE94297}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CppInerop", "lib\local\CppInerop\CppInerop.vcxproj", "{78196985-EE54-411F-822B-5A23EDF80642}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UtilLibs", "UtilLibs", "{D5F7B3E2-01FE-4F4A-8CE1-274D74D395D4}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CamCom", "lib\local\CamCom\CamCom.vcxproj", "{0CEC6A75-17BA-4DC5-9405-C74154921E60}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenFaceOffline", "gui\OpenFaceOffline\OpenFaceOffline.csproj", "{A4760F41-2B1F-4144-B7B2-62785AFFE79B}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32 Debug|Win32 = Debug|Win32
@ -95,12 +105,36 @@ Global
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|Win32.Build.0 = Release|Win32 {DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|Win32.Build.0 = Release|Win32
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.ActiveCfg = Release|x64 {DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.ActiveCfg = Release|x64
{DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.Build.0 = Release|x64 {DDC3535E-526C-44EC-9DF4-739E2D3A323B}.Release|x64.Build.0 = Release|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|Win32.ActiveCfg = Debug|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|Win32.Build.0 = Debug|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|x64.ActiveCfg = Debug|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Debug|x64.Build.0 = Debug|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Release|Win32.ActiveCfg = Release|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Release|Win32.Build.0 = Release|Win32
{78196985-EE54-411F-822B-5A23EDF80642}.Release|x64.ActiveCfg = Release|x64
{78196985-EE54-411F-822B-5A23EDF80642}.Release|x64.Build.0 = Release|x64
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Debug|Win32.ActiveCfg = Debug|Win32
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Debug|Win32.Build.0 = Debug|Win32
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Debug|x64.ActiveCfg = Debug|x64
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Debug|x64.Build.0 = Debug|x64
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Release|Win32.ActiveCfg = Release|Win32
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Release|Win32.Build.0 = Release|Win32
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Release|x64.ActiveCfg = Release|x64
{0CEC6A75-17BA-4DC5-9405-C74154921E60}.Release|x64.Build.0 = Release|x64
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Win32.ActiveCfg = Debug|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|Win32.Build.0 = Debug|x86
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|x64.ActiveCfg = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Debug|x64.Build.0 = Debug|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Win32.ActiveCfg = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|Win32.Build.0 = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|x64.ActiveCfg = Release|Any CPU
{A4760F41-2B1F-4144-B7B2-62785AFFE79B}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{B47A5F12-2567-44E9-AE49-35763EC82149} = {99FEBA13-BDDF-4076-B57E-D8EF4076E20D} {B47A5F12-2567-44E9-AE49-35763EC82149} = {D5F7B3E2-01FE-4F4A-8CE1-274D74D395D4}
{BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8} = {99FEBA13-BDDF-4076-B57E-D8EF4076E20D} {BDC1D107-DE17-4705-8E7B-CDDE8BFB2BF8} = {99FEBA13-BDDF-4076-B57E-D8EF4076E20D}
{0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7} = {99FEBA13-BDDF-4076-B57E-D8EF4076E20D} {0E7FC556-0E80-45EA-A876-DDE4C2FEDCD7} = {99FEBA13-BDDF-4076-B57E-D8EF4076E20D}
{8A23C00D-767D-422D-89A3-CF225E3DAB4B} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631} {8A23C00D-767D-422D-89A3-CF225E3DAB4B} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}
@ -108,5 +142,8 @@ Global
{2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631} {2D80FA0B-2DE8-4475-BA5A-C08A9E1EDAAC} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}
{34032CF2-1B99-4A25-9050-E9C13DD4CD0A} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631} {34032CF2-1B99-4A25-9050-E9C13DD4CD0A} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}
{DDC3535E-526C-44EC-9DF4-739E2D3A323B} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631} {DDC3535E-526C-44EC-9DF4-739E2D3A323B} = {9961DDAC-BE6E-4A6E-8EEF-FFC7D67BD631}
{78196985-EE54-411F-822B-5A23EDF80642} = {D5F7B3E2-01FE-4F4A-8CE1-274D74D395D4}
{0CEC6A75-17BA-4DC5-9405-C74154921E60} = {D5F7B3E2-01FE-4F4A-8CE1-274D74D395D4}
{A4760F41-2B1F-4144-B7B2-62785AFFE79B} = {C9D8D0B0-11EC-41CB-8524-2DDB5BE94297}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View file

@ -0,0 +1,9 @@
<Application x:Class="OpenFaceOffline.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OpenFaceOffline"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View file

@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
namespace OpenFaceOffline
{
public class FpsTracker
{
public TimeSpan HistoryLength { get; set; }
public FpsTracker()
{
HistoryLength = TimeSpan.FromSeconds(2);
}
private Queue<DateTime> frameTimes = new Queue<DateTime>();
private void DiscardOldFrames()
{
while (frameTimes.Count > 0 && (MainWindow.CurrentTime - frameTimes.Peek()) > HistoryLength)
frameTimes.Dequeue();
}
public void AddFrame()
{
frameTimes.Enqueue(MainWindow.CurrentTime);
DiscardOldFrames();
}
public double GetFPS()
{
DiscardOldFrames();
if (frameTimes.Count == 0)
return 0;
return frameTimes.Count / (MainWindow.CurrentTime - frameTimes.Peek()).TotalSeconds;
}
}
}

View file

@ -0,0 +1,171 @@
<Window x:Class="OpenFaceOffline.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:OpenFaceOffline="clr-namespace:OpenFaceOffline"
Title="OpenFace offline" Height="500" Width="1300" MinWidth="700" MinHeight="350" Closing="Window_Closing" WindowStartupLocation="CenterScreen">
<Grid Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2.1*"/>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1.6*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="3*" MinHeight="220"/>
<RowDefinition Height="0.4*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Menu IsMainMenu="True" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4">
<MenuItem Header="File">
<MenuItem Header="Open video(s)" Click="videoFileOpenClick">
</MenuItem>
<MenuItem Header="Open image(s)" Click="imageFileOpenClick">
</MenuItem>
<MenuItem Header="Open image sequence" Click="imageSequenceFileOpenClick">
</MenuItem>
</MenuItem>
<MenuItem Name="RecordingMenu" Header="Recording settings">
<MenuItem Header="Set Location"></MenuItem>
<MenuItem Name="RecordAUCheckBox" IsCheckable="True" Header="Record AUs" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordPoseCheckBox" IsCheckable="True" Header="Record pose" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordLandmarks2DCheckBox" IsCheckable="True" Header="Record 2D landmarks" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordGazeCheckBox" IsCheckable="True" Header="Record gaze" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordLandmarks3DCheckBox" IsCheckable="True" Header="Record 3D landmarks" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordHOGCheckBox" IsCheckable="True" Header="Record HOG" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordParamsCheckBox" IsCheckable="True" Header="Record model parameters" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordAlignedCheckBox" IsCheckable="True" Header="Record aligned faces" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordTrackedVidCheckBox" IsCheckable="True" Header="Record tracked video" Click="recordCheckBox_click"></MenuItem>
</MenuItem>
<MenuItem Header="AU settings">
<MenuItem Name="UseDynamicModelsCheckBox" IsChecked="True" IsCheckable="True" Header="Use dynamic models" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
<MenuItem Name="UseDynamicShiftingCheckBox" IsCheckable="True" Header="Use dynamic shifting" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
<MenuItem Name="UseDynamicScalingCheckBox" IsCheckable="True" Header="Use dynamic scaling" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
</MenuItem>
<MenuItem Header="View">
<MenuItem Name="ShowVideoCheckBox" IsChecked="True" IsCheckable="True" Header="Show Video" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowAppearanceFeaturesCheckBox" IsChecked="True" IsCheckable="True" Header="Show Appearance" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowGeometryFeaturesCheckBox" IsChecked="True" IsCheckable="True" Header="Show Geometry" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowAUsCheckBox" IsChecked="True" IsCheckable="True" Header="Show AUs" Click="VisualisationCheckBox_Click"></MenuItem>
</MenuItem>
</Menu>
<Border Name="VideoBorder" Grid.Row="1" Grid.Column="0" BorderBrush="Black" BorderThickness="1" Background="LightGray" Margin="5,5,0,0">
<OpenFaceOffline:OverlayImage x:Name="video" />
</Border>
<GroupBox Name="AppearanceBorder" Grid.Row="1" Grid.Column="1" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Appearance features
</GroupBox.Header>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0">
<OpenFaceOffline:SimpleImage x:Name="AlignedFace" MaxHeight="150"/>
</Border>
<Border Grid.Row="1">
<OpenFaceOffline:SimpleImage x:Name="AlignedHOG" MaxHeight="150"/>
</Border>
</Grid>
</GroupBox>
<GroupBox Name="GeometryBorder" Grid.Row="1" Grid.Column="2" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Geometry features
</GroupBox.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Width="120" >
<Label Name="headOrientationLabel" FontSize="18" HorizontalContentAlignment="Left">Orientation</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Turn:</Label>
<Label Name="YawLabel" FontSize="12" MinWidth="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Up/down:</Label>
<Label Name="PitchLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Tilt:</Label>
<Label Name="RollLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
</StackPanel>
<Line X1="0" X2="0" Y1="20" Y2="90" Width="2" Stroke="Gray"></Line>
<StackPanel>
<Label Name="headPoseLabel" FontSize="18" HorizontalContentAlignment="Left">Pose</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">X:</Label>
<Label Name="XPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">Y:</Label>
<Label Name="YPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">Z:</Label>
<Label Name="ZPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel>
<StackPanel Width="120" >
<Label Name="gazePanelLabel" FontSize="18" HorizontalContentAlignment="Left">Gaze</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,-5,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Left-right:</Label>
<Label Margin="0,-5,0,0" Name="GazeXLabel" FontSize="12" MinWidth="30" HorizontalContentAlignment="Right">0</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,-5,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Up/down:</Label>
<Label Margin="0,-5,0,0" Name="GazeYLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0</Label>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Center">
<OpenFaceOffline:MultiBarGraph x:Name="nonRigidGraph" HorizontalAlignment="Center" MinHeight="100"/>
<Label HorizontalAlignment="Center">Non rigid parameters</Label>
</StackPanel>
</Grid>
</GroupBox>
<GroupBox Name="ActionUnitBorder" Grid.Row="1" Grid.Column="3" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Action Units
</GroupBox.Header>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<GroupBox>
<GroupBox.Header>
Classification
</GroupBox.Header>
<OpenFaceOffline:MultiBarGraphHorz x:Name="auClassGraph" HorizontalAlignment="Center" MinWidth="100"/>
<!--"<StackPanel Name="AU_classes_panel">
</StackPanel>-->
</GroupBox>
<GroupBox>
<GroupBox.Header>
Regression
</GroupBox.Header>
<OpenFaceOffline:MultiBarGraphHorz x:Name="auRegGraph" HorizontalAlignment="Center" MinWidth="100"/>
</GroupBox>
</StackPanel>
</GroupBox>
<StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Button VerticalAlignment="Top" IsEnabled="False" Click="PauseButton_Click" Name="PauseButton">Pause</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="StopButton_Click" Name="StopButton">Stop</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="ResetButton_Click" Name="ResetButton">Reset</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="SkipButton_Click" Name="NextFrameButton">>> 1</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="SkipButton_Click" Name="NextFiveFramesButton">>> 5</Button>
</StackPanel>
</Grid>
</Window>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9661BE5C-2EE5-495E-BA64-6588602F411B}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenFaceOffline</RootNamespace>
<AssemblyName>OpenFaceOffline</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup>
<StartupObject>
</StartupObject>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>..\..\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="UI_items\BarGraph.xaml.cs">
<DependentUpon>BarGraph.xaml</DependentUpon>
</Compile>
<Compile Include="FpsTracker.cs" />
<Compile Include="UI_items\BarGraphHorizontal.xaml.cs">
<DependentUpon>BarGraphHorizontal.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\MultiBarGraph.xaml.cs">
<DependentUpon>MultiBarGraph.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\MultiBarGraphHorz.xaml.cs">
<DependentUpon>MultiBarGraphHorz.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\SimpleImage.xaml.cs">
<DependentUpon>SimpleImage.xaml</DependentUpon>
</Compile>
<Page Include="UI_items\BarGraph.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\BarGraphHorizontal.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\MultiBarGraph.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="UI_items\MultiBarGraphHorz.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\OverlayImage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\SimpleImage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="UI_items\OverlayImage.xaml.cs">
<DependentUpon>OverlayImage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\lib\local\CppInerop\CppInerop.vcxproj">
<Project>{78196985-ee54-411f-822b-5a23edf80642}</Project>
<Name>CppInerop</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("OpenFaceOffline")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("OpenFaceOffline")]
[assembly: AssemblyCopyright("Copyright © Cambridge 2016")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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")]

View file

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenFaceOffline.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenFaceOffline.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenFaceOffline.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,17 @@
<UserControl x:Class="OpenFaceOffline.BarGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="100">
<StackPanel HorizontalAlignment="Center" >
<Border Name="barContainerPos" Background="PowderBlue" Width="32" DockPanel.Dock="Top" MinHeight="50">
<Rectangle Name="barPos" Fill="CadetBlue" Height="0" VerticalAlignment="Bottom"/>
</Border>
<Border Name="barContainerNeg" Background="PowderBlue" Width="32" MinHeight="50">
<Rectangle Name="barNeg" Fill="CadetBlue" Height="0" VerticalAlignment="Top"/>
</Border>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,39 @@
using System.Windows.Controls;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for BarGraph.xaml
/// </summary>
public partial class BarGraph : UserControl
{
private double targetValue = 0;
public BarGraph()
{
InitializeComponent();
}
public void SetValue(double value)
{
targetValue = 1.5 * value;
if (targetValue > 0)
{
if (targetValue > barContainerPos.ActualHeight)
targetValue = barContainerPos.ActualHeight;
barPos.Height = targetValue;
barNeg.Height = 0;
}
if (targetValue < 0)
{
if (-targetValue > barContainerNeg.ActualHeight)
targetValue = -barContainerNeg.ActualHeight;
barPos.Height = 0;
barNeg.Height = -targetValue;
}
}
}
}

View file

@ -0,0 +1,14 @@
<UserControl x:Class="OpenFaceOffline.BarGraphHorizontal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="200">
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Left" >
<Label Name="Label" FontSize="10" Width="120">AU name</Label>
<Border Name="barContainerPos" Background="PowderBlue" Height="12" DockPanel.Dock="Left" MinWidth="60">
<Rectangle Name="barPos" Fill="CadetBlue" Width="0" HorizontalAlignment="Left"/>
</Border>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for BarGraphHorizontal.xaml
/// </summary>
public partial class BarGraphHorizontal : UserControl
{
double targetValue = 0;
public BarGraphHorizontal(String label)
{
InitializeComponent();
Label.Content = label;
}
public void SetValue(double value)
{
targetValue = value;
barPos.Width = targetValue * barContainerPos.ActualWidth;
}
public double GetTarget()
{
return targetValue;
}
}
}

View file

@ -0,0 +1,11 @@
<UserControl x:Class="OpenFaceOffline.MultiBarGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid Name="barGrid">
</Grid>
</UserControl>

View file

@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for MultiBarGraph.xaml
/// </summary>
public partial class MultiBarGraph : UserControl
{
int num_bars = 0;
List<BarGraph> graphs;
public MultiBarGraph()
{
InitializeComponent();
graphs = new List<BarGraph>();
}
public void Update(List<double> data)
{
// Create new bars if necessary
if (num_bars != data.Count)
{
num_bars = data.Count;
barGrid.Children.Clear();
foreach (var value in data)
{
BarGraph newBar = new BarGraph();
graphs.Add(newBar);
barGrid.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(newBar, graphs.Count);
barGrid.Children.Add(newBar);
}
}
// Update the bars
for (int i = 0; i < data.Count; ++i)
{
graphs[i].SetValue(data[i]);
}
}
}
}

View file

@ -0,0 +1,13 @@
<UserControl x:Class="OpenFaceOffline.MultiBarGraphHorz"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Name="barGrid">
</Grid>
</UserControl>

View file

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for MultiBarGraphHorz.xaml
/// </summary>
public partial class MultiBarGraphHorz : UserControl
{
int num_bars = 0;
Dictionary<String, BarGraphHorizontal> graphs;
// Name mapping
Dictionary<String, String> mapping;
public MultiBarGraphHorz()
{
InitializeComponent();
graphs = new Dictionary<string, BarGraphHorizontal>();
mapping = new Dictionary<string, string>();
mapping["AU01"] = "Inner Brow raiser";
mapping["AU02"] = "Outer Brow raiser";
mapping["AU04"] = "Brow lowerer";
mapping["AU05"] = "Upper lid raiser";
mapping["AU06"] = "Cheek raiser";
mapping["AU07"] = "Lid tightener";
mapping["AU09"] = "Nose wrinkler";
mapping["AU10"] = "Upper lip raiser";
mapping["AU12"] = "Lip corner puller (smile)";
mapping["AU14"] = "Dimpler";
mapping["AU15"] = "Lip corner depressor";
mapping["AU17"] = "Chin Raiser";
mapping["AU20"] = "Lip Stretcher";
mapping["AU23"] = "Lip tightener";
mapping["AU25"] = "Lips part";
mapping["AU26"] = "Jaw drop";
mapping["AU28"] = "Lip suck";
mapping["AU45"] = "Blink";
}
public void Update(Dictionary<String, double> data)
{
// Create new bars if necessary
if (num_bars != data.Count)
{
num_bars = data.Count;
barGrid.Children.Clear();
// Make sure AUs are sorted
var data_labels = data.Keys.ToList();
data_labels.Sort();
foreach (var label in data_labels)
{
BarGraphHorizontal newBar = new BarGraphHorizontal(label + " - " + mapping[label]);
barGrid.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(newBar, graphs.Count);
graphs.Add(label, newBar);
barGrid.Children.Add(newBar);
}
}
// Update the bars
foreach (var value in data)
{
double old_value = graphs[value.Key].GetTarget();
// some smoothing as well
graphs[value.Key].SetValue(old_value * 0.15 + 0.85 * value.Value);
}
}
}
}

View file

@ -0,0 +1,8 @@
<Image x:Class="OpenFaceOffline.OverlayImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
</Image>

View file

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for OverlayImage.xaml
/// </summary>
public partial class OverlayImage : Image
{
public OverlayImage()
{
InitializeComponent();
OverlayLines = new List<Tuple<Point, Point>>();
OverlayPoints = new List<Point>();
GazeLines = new List<Tuple<Point, Point>>();
Progress = -1;
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (OverlayLines == null)
OverlayLines = new List<Tuple<Point, Point>>();
if (OverlayPoints == null)
OverlayPoints = new List<Point>();
if (Source == null || !(Source is WriteableBitmap))
return;
var width = ((WriteableBitmap)Source).PixelWidth;
var height = ((WriteableBitmap)Source).PixelHeight;
foreach (var line in OverlayLines)
{
var p1 = new Point(ActualWidth * line.Item1.X / width, ActualHeight * line.Item1.Y / height);
var p2 = new Point(ActualWidth * line.Item2.X / width, ActualHeight * line.Item2.Y / height);
dc.DrawLine(new Pen(new SolidColorBrush(Color.FromArgb(200, (byte)(100 + (155 * (1 - Confidence))), (byte)(100 + (155 * Confidence)), 100)), 2), p1, p2);
}
foreach (var line in GazeLines)
{
var p1 = new Point(ActualWidth * line.Item1.X / width, ActualHeight * line.Item1.Y / height);
var p2 = new Point(ActualWidth * line.Item2.X / width, ActualHeight * line.Item2.Y / height);
dc.DrawLine(new Pen(new SolidColorBrush(Color.FromArgb(200, (byte)(240), (byte)(30), (byte)100)), 3), p1, p2);
}
foreach (var p in OverlayPoints)
{
var q = new Point(ActualWidth * p.X / width, ActualHeight * p.Y / height);
dc.DrawEllipse(new SolidColorBrush(Color.FromArgb((byte)(200 * Confidence), 255, 255, 100)), null, q, 2, 2);
}
double scaling = ActualWidth / 400.0;
int confidence_width = (int)(107.0 * scaling);
int confidence_height = (int)(18.0 * scaling);
Brush conf_brush = new SolidColorBrush(Color.FromRgb((byte)((1 - Confidence) * 255), (byte)(Confidence * 255), (byte)40));
dc.DrawRoundedRectangle(conf_brush, new Pen(Brushes.Black, 0.5 * scaling), new Rect(ActualWidth - confidence_width - 1, 0, confidence_width, confidence_height), 3.0 * scaling, 3.0 * scaling);
FormattedText txt = new FormattedText("Confidence: " + (int)(100 * Confidence) + "%", System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface("Verdana"), 12.0 * scaling, Brushes.Black);
dc.DrawText(txt, new Point(ActualWidth - confidence_width + 2, 2));
int fps_width = (int)(52.0 * scaling);
int fps_height = (int)(18.0 * scaling);
dc.DrawRoundedRectangle(Brushes.WhiteSmoke, new Pen(Brushes.Black, 0.5 * scaling), new Rect(0, 0, fps_width, fps_height), 3.0 * scaling, 3.0 * scaling);
FormattedText fps_txt = new FormattedText("FPS: " + (int)FPS, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface("Verdana"), 12.0 * scaling, Brushes.Black);
dc.DrawText(fps_txt, new Point(2.0 * scaling, 0));
old_width = width;
old_height = height;
// Drawing a progress bar at the bottom of the image
if (Progress > 0)
{
int progress_bar_height = (int)(6.0 * scaling);
dc.DrawRectangle(Brushes.GreenYellow, new Pen(Brushes.Black, 0.5 * scaling), new Rect(0, ActualHeight - progress_bar_height, Progress * ActualWidth, progress_bar_height));
}
}
public List<Tuple<Point, Point>> OverlayLines { get; set; }
public List<Tuple<Point, Point>> GazeLines { get; set; }
public List<Point> OverlayPoints { get; set; }
public double Confidence { get; set; }
public double FPS { get; set; }
// 0 to 1 indicates how much video has been processed so far
public double Progress { get; set; }
int old_width;
int old_height;
}
}

View file

@ -0,0 +1,8 @@
<Image x:Class="OpenFaceOffline.SimpleImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
</Image>

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for OverlayImage.xaml
/// </summary>
public partial class SimpleImage : Image
{
public SimpleImage()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (Source == null || !(Source is WriteableBitmap))
return;
}
}
}

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>

View file

@ -0,0 +1,9 @@
<Application x:Class="OpenFaceOffline.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:OpenFaceOffline"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View file

@ -0,0 +1,75 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View file

@ -0,0 +1,96 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
namespace OpenFaceOffline
{
public class FpsTracker
{
public TimeSpan HistoryLength { get; set; }
public FpsTracker()
{
HistoryLength = TimeSpan.FromSeconds(2);
}
private Queue<DateTime> frameTimes = new Queue<DateTime>();
private void DiscardOldFrames()
{
while (frameTimes.Count > 0 && (MainWindow.CurrentTime - frameTimes.Peek()) > HistoryLength)
frameTimes.Dequeue();
}
public void AddFrame()
{
frameTimes.Enqueue(MainWindow.CurrentTime);
DiscardOldFrames();
}
public double GetFPS()
{
DiscardOldFrames();
if (frameTimes.Count == 0)
return 0;
return frameTimes.Count / (MainWindow.CurrentTime - frameTimes.Peek()).TotalSeconds;
}
}
}

View file

@ -0,0 +1,175 @@
<Window x:Class="OpenFaceOffline.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OpenFaceOffline"
xmlns:OpenFaceOffline="clr-namespace:OpenFaceOffline"
mc:Ignorable="d"
Title="OpenFace offline" Height="500" Width="1300" MinWidth="700" MinHeight="350" Closing="Window_Closing" WindowStartupLocation="CenterScreen">
<Grid Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2.1*"/>
<ColumnDefinition Width="0.8*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1.6*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="3*" MinHeight="220"/>
<RowDefinition Height="0.4*"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Menu IsMainMenu="True" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4">
<MenuItem Header="File">
<MenuItem Header="Open video(s)" Click="videoFileOpenClick">
</MenuItem>
<MenuItem Header="Open image(s)" Click="imageFileOpenClick">
</MenuItem>
<MenuItem Header="Open image sequence" Click="imageSequenceFileOpenClick">
</MenuItem>
</MenuItem>
<MenuItem Name="RecordingMenu" Header="Recording settings">
<MenuItem Header="Set Location"></MenuItem>
<MenuItem Name="RecordAUCheckBox" IsCheckable="True" Header="Record AUs" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordPoseCheckBox" IsCheckable="True" Header="Record pose" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordLandmarks2DCheckBox" IsCheckable="True" Header="Record 2D landmarks" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordGazeCheckBox" IsCheckable="True" Header="Record gaze" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordLandmarks3DCheckBox" IsCheckable="True" Header="Record 3D landmarks" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordHOGCheckBox" IsCheckable="True" Header="Record HOG" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordParamsCheckBox" IsCheckable="True" Header="Record model parameters" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordAlignedCheckBox" IsCheckable="True" Header="Record aligned faces" Click="recordCheckBox_click"></MenuItem>
<MenuItem Name="RecordTrackedVidCheckBox" IsCheckable="True" Header="Record tracked video" Click="recordCheckBox_click"></MenuItem>
</MenuItem>
<MenuItem Header="AU settings">
<MenuItem Name="UseDynamicModelsCheckBox" IsChecked="True" IsCheckable="True" Header="Use dynamic models" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
<MenuItem Name="UseDynamicShiftingCheckBox" IsCheckable="True" Header="Use dynamic shifting" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
<MenuItem Name="UseDynamicScalingCheckBox" IsCheckable="True" Header="Use dynamic scaling" Click="UseDynamicModelsCheckBox_Click"></MenuItem>
</MenuItem>
<MenuItem Header="View">
<MenuItem Name="ShowVideoCheckBox" IsChecked="True" IsCheckable="True" Header="Show Video" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowAppearanceFeaturesCheckBox" IsChecked="True" IsCheckable="True" Header="Show Appearance" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowGeometryFeaturesCheckBox" IsChecked="True" IsCheckable="True" Header="Show Geometry" Click="VisualisationCheckBox_Click"></MenuItem>
<MenuItem Name="ShowAUsCheckBox" IsChecked="True" IsCheckable="True" Header="Show AUs" Click="VisualisationCheckBox_Click"></MenuItem>
</MenuItem>
</Menu>
<Border Name="VideoBorder" Grid.Row="1" Grid.Column="0" BorderBrush="Black" BorderThickness="1" Background="LightGray" Margin="5,5,0,0">
<OpenFaceOffline:OverlayImage x:Name="video" />
</Border>
<GroupBox Name="AppearanceBorder" Grid.Row="1" Grid.Column="1" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Appearance features
</GroupBox.Header>
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Grid.Row="0">
<OpenFaceOffline:SimpleImage x:Name="AlignedFace" MaxHeight="150"/>
</Border>
<Border Grid.Row="1">
<OpenFaceOffline:SimpleImage x:Name="AlignedHOG" MaxHeight="150"/>
</Border>
</Grid>
</GroupBox>
<GroupBox Name="GeometryBorder" Grid.Row="1" Grid.Column="2" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Geometry features
</GroupBox.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Grid.Row="0" >
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Width="120" >
<Label Name="headOrientationLabel" FontSize="18" HorizontalContentAlignment="Left">Orientation</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Turn:</Label>
<Label Name="YawLabel" FontSize="12" MinWidth="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Up/down:</Label>
<Label Name="PitchLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Tilt:</Label>
<Label Name="RollLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0°</Label>
</StackPanel>
</StackPanel>
<Line X1="0" X2="0" Y1="20" Y2="90" Width="2" Stroke="Gray"></Line>
<StackPanel>
<Label Name="headPoseLabel" FontSize="18" HorizontalContentAlignment="Left">Pose</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">X:</Label>
<Label Name="XPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">Y:</Label>
<Label Name="YPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,0,0,0" FontSize="12" HorizontalContentAlignment="Left" Width="20">Z:</Label>
<Label Name="ZPoseLabel" FontSize="12" HorizontalContentAlignment="Right" Width="50">0 mm</Label>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel>
<StackPanel Width="120" >
<Label Name="gazePanelLabel" FontSize="18" HorizontalContentAlignment="Left">Gaze</Label>
<StackPanel Orientation="Horizontal">
<Label Margin="5,-5,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Left-right:</Label>
<Label Margin="0,-5,0,0" Name="GazeXLabel" FontSize="12" MinWidth="30" HorizontalContentAlignment="Right">0</Label>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Margin="5,-5,0,0" FontSize="12" Width="60" HorizontalContentAlignment="Left">Up/down:</Label>
<Label Margin="0,-5,0,0" Name="GazeYLabel" FontSize="12" Width="30" HorizontalContentAlignment="Right">0</Label>
</StackPanel>
</StackPanel>
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Center">
<OpenFaceOffline:MultiBarGraph x:Name="nonRigidGraph" HorizontalAlignment="Center" MinHeight="100"/>
<Label HorizontalAlignment="Center">Non rigid parameters</Label>
</StackPanel>
</Grid>
</GroupBox>
<GroupBox Name="ActionUnitBorder" Grid.Row="1" Grid.Column="3" BorderBrush="Black" BorderThickness="1" MinHeight="100">
<GroupBox.Header>
Action Units
</GroupBox.Header>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<GroupBox>
<GroupBox.Header>
Classification
</GroupBox.Header>
<OpenFaceOffline:MultiBarGraphHorz x:Name="auClassGraph" HorizontalAlignment="Center" MinWidth="100"/>
<!--"<StackPanel Name="AU_classes_panel">
</StackPanel>-->
</GroupBox>
<GroupBox>
<GroupBox.Header>
Regression
</GroupBox.Header>
<OpenFaceOffline:MultiBarGraphHorz x:Name="auRegGraph" HorizontalAlignment="Center" MinWidth="100"/>
</GroupBox>
</StackPanel>
</GroupBox>
<StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
<Button VerticalAlignment="Top" IsEnabled="False" Click="PauseButton_Click" Name="PauseButton">Pause</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="StopButton_Click" Name="StopButton">Stop</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="ResetButton_Click" Name="ResetButton">Reset</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="SkipButton_Click" Name="NextFrameButton">>> 1</Button>
<Button VerticalAlignment="Top" IsEnabled="False" Click="SkipButton_Click" Name="NextFiveFramesButton">>> 5</Button>
</StackPanel>
</Grid>
</Window>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,184 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A4760F41-2B1F-4144-B7B2-62785AFFE79B}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>OpenFaceOffline</RootNamespace>
<AssemblyName>OpenFaceOffline</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\..\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>..\..\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>logo1.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="FpsTracker.cs" />
<Compile Include="UI_items\BarGraph.xaml.cs">
<DependentUpon>BarGraph.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\BarGraphHorizontal.xaml.cs">
<DependentUpon>BarGraphHorizontal.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\MultiBarGraph.xaml.cs">
<DependentUpon>MultiBarGraph.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\MultiBarGraphHorz.xaml.cs">
<DependentUpon>MultiBarGraphHorz.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\OverlayImage.xaml.cs">
<DependentUpon>OverlayImage.xaml</DependentUpon>
</Compile>
<Compile Include="UI_items\SimpleImage.xaml.cs">
<DependentUpon>SimpleImage.xaml</DependentUpon>
</Compile>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Page Include="UI_items\BarGraph.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\BarGraphHorizontal.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\MultiBarGraph.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\MultiBarGraphHorz.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\OverlayImage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UI_items\SimpleImage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\lib\local\CppInerop\CppInerop.vcxproj">
<Project>{78196985-ee54-411f-822b-5a23edf80642}</Project>
<Name>CppInerop</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="logo1.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PreBuildEvent>xcopy /I /E /Y /D "$(ProjectDir)logo1.ico" "$(SolutionDir)/$(Configuration)"</PreBuildEvent>
</PropertyGroup>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
// 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("OpenFaceOffline")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("OpenFaceOffline")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2016")]
[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)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// 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")]

View file

@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenFaceOffline.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources
{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager
{
get
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OpenFaceOffline.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace OpenFaceOffline.Properties
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default
{
get
{
return defaultInstance;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,17 @@
<UserControl x:Class="OpenFaceOffline.BarGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="100">
<StackPanel HorizontalAlignment="Center" >
<Border Name="barContainerPos" Background="PowderBlue" Width="32" DockPanel.Dock="Top" MinHeight="50">
<Rectangle Name="barPos" Fill="CadetBlue" Height="0" VerticalAlignment="Bottom"/>
</Border>
<Border Name="barContainerNeg" Background="PowderBlue" Width="32" MinHeight="50">
<Rectangle Name="barNeg" Fill="CadetBlue" Height="0" VerticalAlignment="Top"/>
</Border>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,97 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System.Windows.Controls;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for BarGraph.xaml
/// </summary>
public partial class BarGraph : UserControl
{
private double targetValue = 0;
public BarGraph()
{
InitializeComponent();
}
public void SetValue(double value)
{
targetValue = 1.5 * value;
if (targetValue > 0)
{
if (targetValue > barContainerPos.ActualHeight)
targetValue = barContainerPos.ActualHeight;
barPos.Height = targetValue;
barNeg.Height = 0;
}
if (targetValue < 0)
{
if (-targetValue > barContainerNeg.ActualHeight)
targetValue = -barContainerNeg.ActualHeight;
barPos.Height = 0;
barNeg.Height = -targetValue;
}
}
}
}

View file

@ -0,0 +1,14 @@
<UserControl x:Class="OpenFaceOffline.BarGraphHorizontal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="200">
<StackPanel VerticalAlignment="Center" Orientation="Horizontal" HorizontalAlignment="Left" >
<Label Name="Label" FontSize="10" Width="120">AU name</Label>
<Border Name="barContainerPos" Background="PowderBlue" Height="12" DockPanel.Dock="Left" MinWidth="60">
<Rectangle Name="barPos" Fill="CadetBlue" Width="0" HorizontalAlignment="Left"/>
</Border>
</StackPanel>
</UserControl>

View file

@ -0,0 +1,100 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for BarGraphHorizontal.xaml
/// </summary>
public partial class BarGraphHorizontal : UserControl
{
double targetValue = 0;
public BarGraphHorizontal(String label)
{
InitializeComponent();
Label.Content = label;
}
public void SetValue(double value)
{
targetValue = value;
barPos.Width = targetValue * barContainerPos.ActualWidth;
}
public double GetTarget()
{
return targetValue;
}
}
}

View file

@ -0,0 +1,11 @@
<UserControl x:Class="OpenFaceOffline.MultiBarGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="100" d:DesignWidth="300">
<Grid Name="barGrid">
</Grid>
</UserControl>

View file

@ -0,0 +1,117 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for MultiBarGraph.xaml
/// </summary>
public partial class MultiBarGraph : UserControl
{
int num_bars = 0;
List<BarGraph> graphs;
public MultiBarGraph()
{
InitializeComponent();
graphs = new List<BarGraph>();
}
public void Update(List<double> data)
{
// Create new bars if necessary
if (num_bars != data.Count)
{
num_bars = data.Count;
barGrid.Children.Clear();
foreach (var value in data)
{
BarGraph newBar = new BarGraph();
graphs.Add(newBar);
barGrid.ColumnDefinitions.Add(new ColumnDefinition());
Grid.SetColumn(newBar, graphs.Count);
barGrid.Children.Add(newBar);
}
}
// Update the bars
for (int i = 0; i < data.Count; ++i)
{
graphs[i].SetValue(data[i]);
}
}
}
}

View file

@ -0,0 +1,13 @@
<UserControl x:Class="OpenFaceOffline.MultiBarGraphHorz"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Name="barGrid">
</Grid>
</UserControl>

View file

@ -0,0 +1,148 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for MultiBarGraphHorz.xaml
/// </summary>
public partial class MultiBarGraphHorz : UserControl
{
int num_bars = 0;
Dictionary<String, BarGraphHorizontal> graphs;
// Name mapping
Dictionary<String, String> mapping;
public MultiBarGraphHorz()
{
InitializeComponent();
graphs = new Dictionary<string, BarGraphHorizontal>();
mapping = new Dictionary<string, string>();
mapping["AU01"] = "Inner Brow raiser";
mapping["AU02"] = "Outer Brow raiser";
mapping["AU04"] = "Brow lowerer";
mapping["AU05"] = "Upper lid raiser";
mapping["AU06"] = "Cheek raiser";
mapping["AU07"] = "Lid tightener";
mapping["AU09"] = "Nose wrinkler";
mapping["AU10"] = "Upper lip raiser";
mapping["AU12"] = "Lip corner puller (smile)";
mapping["AU14"] = "Dimpler";
mapping["AU15"] = "Lip corner depressor";
mapping["AU17"] = "Chin Raiser";
mapping["AU20"] = "Lip Stretcher";
mapping["AU23"] = "Lip tightener";
mapping["AU25"] = "Lips part";
mapping["AU26"] = "Jaw drop";
mapping["AU28"] = "Lip suck";
mapping["AU45"] = "Blink";
}
public void Update(Dictionary<String, double> data)
{
// Create new bars if necessary
if (num_bars != data.Count)
{
num_bars = data.Count;
barGrid.Children.Clear();
// Make sure AUs are sorted
var data_labels = data.Keys.ToList();
data_labels.Sort();
foreach (var label in data_labels)
{
BarGraphHorizontal newBar = new BarGraphHorizontal(label + " - " + mapping[label]);
barGrid.RowDefinitions.Add(new RowDefinition());
Grid.SetRow(newBar, graphs.Count);
graphs.Add(label, newBar);
barGrid.Children.Add(newBar);
}
}
// Update the bars
foreach (var value in data)
{
double old_value = graphs[value.Key].GetTarget();
// some smoothing as well
graphs[value.Key].SetValue(old_value * 0.15 + 0.85 * value.Value);
}
}
}
}

View file

@ -0,0 +1,8 @@
<Image x:Class="OpenFaceOffline.OverlayImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
</Image>

View file

@ -0,0 +1,168 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for OverlayImage.xaml
/// </summary>
public partial class OverlayImage : Image
{
public OverlayImage()
{
InitializeComponent();
OverlayLines = new List<Tuple<Point, Point>>();
OverlayPoints = new List<Point>();
GazeLines = new List<Tuple<Point, Point>>();
Progress = -1;
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (OverlayLines == null)
OverlayLines = new List<Tuple<Point, Point>>();
if (OverlayPoints == null)
OverlayPoints = new List<Point>();
if (Source == null || !(Source is WriteableBitmap))
return;
var width = ((WriteableBitmap)Source).PixelWidth;
var height = ((WriteableBitmap)Source).PixelHeight;
foreach (var line in OverlayLines)
{
var p1 = new Point(ActualWidth * line.Item1.X / width, ActualHeight * line.Item1.Y / height);
var p2 = new Point(ActualWidth * line.Item2.X / width, ActualHeight * line.Item2.Y / height);
dc.DrawLine(new Pen(new SolidColorBrush(Color.FromArgb(200, (byte)(100 + (155 * (1 - Confidence))), (byte)(100 + (155 * Confidence)), 100)), 2), p1, p2);
}
foreach (var line in GazeLines)
{
var p1 = new Point(ActualWidth * line.Item1.X / width, ActualHeight * line.Item1.Y / height);
var p2 = new Point(ActualWidth * line.Item2.X / width, ActualHeight * line.Item2.Y / height);
dc.DrawLine(new Pen(new SolidColorBrush(Color.FromArgb(200, (byte)(240), (byte)(30), (byte)100)), 3), p1, p2);
}
foreach (var p in OverlayPoints)
{
var q = new Point(ActualWidth * p.X / width, ActualHeight * p.Y / height);
dc.DrawEllipse(new SolidColorBrush(Color.FromArgb((byte)(200 * Confidence), 255, 255, 100)), null, q, 2, 2);
}
double scaling = ActualWidth / 400.0;
int confidence_width = (int)(107.0 * scaling);
int confidence_height = (int)(18.0 * scaling);
Brush conf_brush = new SolidColorBrush(Color.FromRgb((byte)((1 - Confidence) * 255), (byte)(Confidence * 255), (byte)40));
dc.DrawRoundedRectangle(conf_brush, new Pen(Brushes.Black, 0.5 * scaling), new Rect(ActualWidth - confidence_width - 1, 0, confidence_width, confidence_height), 3.0 * scaling, 3.0 * scaling);
FormattedText txt = new FormattedText("Confidence: " + (int)(100 * Confidence) + "%", System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface("Verdana"), 12.0 * scaling, Brushes.Black);
dc.DrawText(txt, new Point(ActualWidth - confidence_width + 2, 2));
int fps_width = (int)(52.0 * scaling);
int fps_height = (int)(18.0 * scaling);
dc.DrawRoundedRectangle(Brushes.WhiteSmoke, new Pen(Brushes.Black, 0.5 * scaling), new Rect(0, 0, fps_width, fps_height), 3.0 * scaling, 3.0 * scaling);
FormattedText fps_txt = new FormattedText("FPS: " + (int)FPS, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface("Verdana"), 12.0 * scaling, Brushes.Black);
dc.DrawText(fps_txt, new Point(2.0 * scaling, 0));
old_width = width;
old_height = height;
// Drawing a progress bar at the bottom of the image
if (Progress > 0)
{
int progress_bar_height = (int)(6.0 * scaling);
dc.DrawRectangle(Brushes.GreenYellow, new Pen(Brushes.Black, 0.5 * scaling), new Rect(0, ActualHeight - progress_bar_height, Progress * ActualWidth, progress_bar_height));
}
}
public List<Tuple<Point, Point>> OverlayLines { get; set; }
public List<Tuple<Point, Point>> GazeLines { get; set; }
public List<Point> OverlayPoints { get; set; }
public double Confidence { get; set; }
public double FPS { get; set; }
// 0 to 1 indicates how much video has been processed so far
public double Progress { get; set; }
int old_width;
int old_height;
}
}

View file

@ -0,0 +1,8 @@
<Image x:Class="OpenFaceOffline.SimpleImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" >
</Image>

View file

@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016, Carnegie Mellon University and University of Cambridge,
// all rights reserved.
//
// THIS SOFTWARE IS PROVIDED “AS IS” FOR ACADEMIC USE ONLY AND ANY EXPRESS
// OR IMPLIED WARRANTIES WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS
// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY.
// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Notwithstanding the license granted herein, Licensee acknowledges that certain components
// of the Software may be covered by so-called “open source” software licenses (“Open Source
// Components”), which means any software licenses approved as open source licenses by the
// Open Source Initiative or any substantially similar licenses, including without limitation any
// license that, as a condition of distribution of the software licensed under such license,
// requires that the distributor make the software available in source code format. Licensor shall
// provide a list of Open Source Components for a particular version of the Software upon
// Licensees request. Licensee will comply with the applicable terms of such licenses and to
// the extent required by the licenses covering Open Source Components, the terms of such
// licenses will apply in lieu of the terms of this Agreement. To the extent the terms of the
// licenses applicable to Open Source Components prohibit any of the restrictions in this
// License Agreement with respect to such Open Source Component, such restrictions will not
// apply to such Open Source Component. To the extent the terms of the licenses applicable to
// Open Source Components require Licensor to make an offer to provide source code or
// related information in connection with the Software, such offer is hereby made. Any request
// for source code or related information should be directed to cl-face-tracker-distribution@lists.cam.ac.uk
// Licensee acknowledges receipt of notices for the Open Source Components for the initial
// delivery of the Software.
// * Any publications arising from the use of this software, including but
// not limited to academic journal and conference publications, technical
// reports and manuals, must cite at least one of the following works:
//
// OpenFace: an open source facial behavior analysis toolkit
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency
// in IEEE Winter Conference on Applications of Computer Vision, 2016
//
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
// in IEEE International. Conference on Computer Vision (ICCV), 2015
//
// Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
// in Facial Expression Recognition and Analysis Challenge,
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
//
// Constrained Local Neural Fields for robust facial landmark detection in the wild.
// Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency.
// in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace OpenFaceOffline
{
/// <summary>
/// Interaction logic for OverlayImage.xaml
/// </summary>
public partial class SimpleImage : Image
{
public SimpleImage()
{
InitializeComponent();
}
protected override void OnRender(DrawingContext dc)
{
base.OnRender(dc);
if (Source == null || !(Source is WriteableBitmap))
return;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)lib\local\CamCom;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>dxva2.lib;evr.lib;mf.lib;mfplat.lib;mfplay.lib;mfreadwrite.lib;mfuuid.lib;Strmiids.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

View file

@ -0,0 +1,167 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{0CEC6A75-17BA-4DC5-9405-C74154921E60}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>CamCom</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\3rdParty\OpenCV3.1\openCV3.1.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\3rdParty\OpenCV3.1\openCV3.1.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\3rdParty\OpenCV3.1\openCV3.1.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\..\3rdParty\OpenCV3.1\openCV3.1.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>./;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="camera_helper.h" />
<ClInclude Include="comet_auto_mf.h" />
<ClInclude Include="comet_com_ptr_array.h" />
<ClInclude Include="comet_task_ptr.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="camera_helper.cpp" />
<ClCompile Include="stdafx.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="camera_helper.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="comet_auto_mf.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="comet_com_ptr_array.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="comet_task_ptr.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="camera_helper.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View file

@ -0,0 +1,192 @@
#include "stdafx.h"
#include "camera_helper.h"
//#include <format.h>
namespace {
namespace internal {
template<camera::Property property> struct property_traits {};
template<long Id>
struct camera_control_property_traits
{
typedef IAMCameraControl Interface;
static long id() { return Id; }
};
template<long Id>
struct video_proc_amp_property_traits
{
typedef IAMVideoProcAmp Interface;
static long id() { return Id; }
};
template<> struct property_traits < camera::Exposure > : public camera_control_property_traits<CameraControl_Exposure> {};
template<> struct property_traits < camera::Focus > : public camera_control_property_traits<CameraControl_Focus>{};
template<> struct property_traits < camera::Zoom > : public camera_control_property_traits<CameraControl_Zoom>{};
template<> struct property_traits < camera::Pan > : public camera_control_property_traits<CameraControl_Pan>{};
template<> struct property_traits < camera::Tilt > : public camera_control_property_traits<CameraControl_Tilt>{};
template<> struct property_traits < camera::Roll > : public camera_control_property_traits<CameraControl_Roll>{};
template<> struct property_traits < camera::Iris > : public camera_control_property_traits<CameraControl_Iris>{};
template<> struct property_traits < camera::Brightness > : public video_proc_amp_property_traits<VideoProcAmp_Brightness>{};
template<> struct property_traits < camera::Contrast > : public video_proc_amp_property_traits<VideoProcAmp_Contrast>{};
template<> struct property_traits < camera::Hue > : public video_proc_amp_property_traits<VideoProcAmp_Hue>{};
template<> struct property_traits < camera::Saturation > : public video_proc_amp_property_traits<VideoProcAmp_Saturation>{};
template<> struct property_traits < camera::Sharpness > : public video_proc_amp_property_traits<VideoProcAmp_Sharpness>{};
template<> struct property_traits < camera::Gamma > : public video_proc_amp_property_traits<VideoProcAmp_Gamma>{};
template<> struct property_traits < camera::ColorEnable > : public video_proc_amp_property_traits<VideoProcAmp_ColorEnable>{};
template<> struct property_traits < camera::WhiteBalance > : public video_proc_amp_property_traits<VideoProcAmp_WhiteBalance>{};
template<> struct property_traits < camera::BacklightCompensation > : public video_proc_amp_property_traits<VideoProcAmp_BacklightCompensation>{};
template<> struct property_traits < camera::Gain > : public video_proc_amp_property_traits < VideoProcAmp_Gain > {};
template<typename Interface> struct interface_traits {};
template<> struct interface_traits < IAMCameraControl >
{
static long auto_flag() { return CameraControl_Flags_Auto; }
static long manual_flag() { return CameraControl_Flags_Manual; }
};
template<> struct interface_traits<IAMVideoProcAmp>
{
static long auto_flag() { return VideoProcAmp_Flags_Auto; }
static long manual_flag() { return VideoProcAmp_Flags_Manual; }
};
template<typename Interface, typename SourcePtr>
bool has(long id, const SourcePtr& source_ptr) {
comet::com_ptr<Interface> pInterface = comet::com_cast(source_ptr);
if (!pInterface) return false;
long value, flags;
HRESULT hr = pInterface->Get(id, &value, &flags);
return SUCCEEDED(hr);
}
template<typename Interface, typename SourcePtr>
cam_prop_range get_range(long id, const SourcePtr& source_ptr) {
comet::com_ptr<Interface> pInterface = comet::try_cast(source_ptr);
cam_prop_range range;
long flags;
pInterface->GetRange(id, &range.min, &range.max, &range.step, &range.defaultValue, &flags) | comet::raise_exception;
range.canBeAuto = (flags & interface_traits<Interface>::auto_flag()) != 0;
range.canBeManual = (flags & interface_traits<Interface>::manual_flag()) != 0;
return range;
}
template<typename Interface, typename SourcePtr>
cam_prop_value get(long id, const SourcePtr& source_ptr) {
comet::com_ptr<Interface> pInterface = comet::try_cast(source_ptr);
cam_prop_value value;
long flags;
pInterface->Get(id, &value.value, &flags) | comet::raise_exception;
value.isAuto = (flags & interface_traits<Interface>::auto_flag()) != 0 || (flags & interface_traits<Interface>::manual_flag()) == 0;
return value;
}
template<typename Interface, typename SourcePtr>
void set(long id, const cam_prop_value& value, const SourcePtr& source_ptr) {
comet::com_ptr<Interface> pInterface = comet::try_cast(source_ptr);
long flags = value.isAuto ? interface_traits<Interface>::auto_flag() : interface_traits<Interface>::manual_flag();
pInterface->Set(id, value.value, flags) | comet::raise_exception;
}
}
}
#define MAP_OVER_CAMERA_PROPERTIES(FUNC) \
FUNC(::camera::Exposure, Exposure) \
FUNC(::camera::Focus, Focus) \
FUNC(::camera::Zoom, Zoom) \
FUNC(::camera::Pan, Pan) \
FUNC(::camera::Tilt, Tilt) \
FUNC(::camera::Roll, Roll) \
FUNC(::camera::Iris, Iris) \
FUNC(::camera::Brightness, Brightness) \
FUNC(::camera::Contrast, Contrast) \
FUNC(::camera::Hue, Hue) \
FUNC(::camera::Saturation, Saturation) \
FUNC(::camera::Sharpness, Sharpness) \
FUNC(::camera::Gamma, Gamma) \
FUNC(::camera::ColorEnable, Color Enable) \
FUNC(::camera::WhiteBalance, White Balance) \
FUNC(::camera::BacklightCompensation, Backlight Compensation) \
FUNC(::camera::Gain, Gain)
bool camera::has(Property property) const
{
switch (property) {
#define CASE(PROP, NAME) case PROP: return ::internal::has<::internal::property_traits<PROP>::Interface>(::internal::property_traits<PROP>::id(), source_ptr);
MAP_OVER_CAMERA_PROPERTIES(CASE)
#undef CASE
default:
return false;
}
}
cam_prop_range camera::get_range(Property property) const
{
switch (property) {
#define CASE(PROP, NAME) case PROP: return ::internal::get_range<::internal::property_traits<PROP>::Interface>(::internal::property_traits<PROP>::id(), source_ptr);
MAP_OVER_CAMERA_PROPERTIES(CASE)
#undef CASE
default:
throw std::runtime_error("No such property: " + std::string(camera::property_name(property)));
}
}
cam_prop_value camera::get(Property property) const
{
switch (property) {
#define CASE(PROP, NAME) case PROP: return ::internal::get<::internal::property_traits<PROP>::Interface>(::internal::property_traits<PROP>::id(), source_ptr);
MAP_OVER_CAMERA_PROPERTIES(CASE)
#undef CASE
default:
throw std::runtime_error("No such property: " + std::string(camera::property_name(property)));
}
}
void camera::set(Property property, const cam_prop_value& value)
{
switch (property) {
#define CASE(PROP, NAME) case PROP: ::internal::set<::internal::property_traits<PROP>::Interface>(::internal::property_traits<PROP>::id(), value, source_ptr); break;
MAP_OVER_CAMERA_PROPERTIES(CASE)
#undef CASE
}
}
std::vector<camera::Property> camera::list_properties()
{
std::vector<camera::Property> properties;
properties.push_back(Exposure); // CameraControl
properties.push_back(Focus);
properties.push_back(Zoom);
properties.push_back(Pan);
properties.push_back(Tilt);
properties.push_back(Roll);
properties.push_back(Iris);
properties.push_back(Brightness);
properties.push_back(Contrast);
properties.push_back(Hue);
properties.push_back(Saturation);
properties.push_back(Sharpness);
properties.push_back(Gamma);
properties.push_back(ColorEnable);
properties.push_back(WhiteBalance);
properties.push_back(BacklightCompensation);
properties.push_back(Gain);
return properties;
//#define PROPENTRY(PROP, NAME) PROP,
// MAP_OVER_CAMERA_PROPERTIES(PROPENTRY)
//#undef PROPENTRY
// };
}
const char* camera::property_name(Property property)
{
switch (property) {
#define CASE(PROP, NAME) case PROP: return #NAME;
MAP_OVER_CAMERA_PROPERTIES(CASE)
#undef CASE
default:
return "UNKNOWN";
}
}

View file

@ -0,0 +1,720 @@
#ifndef camera_helper_h__
#define camera_helper_h__
#pragma once
#include <vector>
#include <cv.h>
#include <highgui.h>
#include <opencv2/imgcodecs.hpp>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <mferror.h>
#include <DShow.h>
#include <comet/ptr.h>
#include <comet_task_ptr.h>
#include <comet_com_ptr_array.h>
namespace comet {
#define MAKE_COMET_COMTYPE(T, BASE) \
template<> struct comtype< ::T > \
{ \
static const IID& uuid() { return IID_ ## T; } \
typedef ::BASE base; \
}
MAKE_COMET_COMTYPE(IMF2DBuffer, IUnknown);
MAKE_COMET_COMTYPE(IAMVideoProcAmp, IUnknown);
MAKE_COMET_COMTYPE(IAMCameraControl, IUnknown);
}
struct cam_prop_range
{
long min;
long max;
long step;
long defaultValue;
bool canBeAuto;
bool canBeManual;
};
inline std::ostream& operator<<(std::ostream& os, const cam_prop_range& val)
{
os << "[" << val.min << ":" << val.step << ":" << val.max << "], " << val.defaultValue;
if (val.canBeAuto && val.canBeManual)
os << " (auto/manual)";
else if (val.canBeAuto)
os << " (auto)";
else if (val.canBeManual)
os << " (manual)";
return os;
}
struct cam_prop_value
{
long value;
bool isAuto;
cam_prop_value() : value(0), isAuto(true)
{
}
cam_prop_value(long value, bool isAuto = false) : value(value), isAuto(isAuto)
{
}
operator long() const
{
return value;
}
static cam_prop_value AUTO(long value = 0) {
return cam_prop_value(value, true);
};
static cam_prop_value MANUAL(long value = 0) {
return cam_prop_value(value, false);
};
};
inline std::ostream& operator<<(std::ostream& os, const cam_prop_value& val)
{
os << val.value;
os << " (";
if (val.isAuto)
os << "auto";
else
os << "manual";
os << ")";
return os;
}
namespace MediaFormat
{
enum e
{
Unknown,
RGB32, // MFVideoFormat_RGB32
ARGB32, // MFVideoFormat_ARGB32
RGB24, // MFVideoFormat_RGB24
RGB555, // MFVideoFormat_RGB555
RGB565, // MFVideoFormat_RGB565
RGB8, // MFVideoFormat_RGB8
AI44, // MFVideoFormat_AI44
AYUV, // MFVideoFormat_AYUV
YUY2, // MFVideoFormat_YUY2
YVYU, // MFVideoFormat_YVYU
YVU9, // MFVideoFormat_YVU9
UYVY, // MFVideoFormat_UYVY
NV11, // MFVideoFormat_NV11
NV12, // MFVideoFormat_NV12
YV12, // MFVideoFormat_YV12
I420, // MFVideoFormat_I420
IYUV, // MFVideoFormat_IYUV
Y210, // MFVideoFormat_Y210
Y216, // MFVideoFormat_Y216
Y410, // MFVideoFormat_Y410
Y416, // MFVideoFormat_Y416
Y41P, // MFVideoFormat_Y41P
Y41T, // MFVideoFormat_Y41T
Y42T, // MFVideoFormat_Y42T
P210, // MFVideoFormat_P210
P216, // MFVideoFormat_P216
P010, // MFVideoFormat_P010
P016, // MFVideoFormat_P016
v210, // MFVideoFormat_v210
v216, // MFVideoFormat_v216
v410, // MFVideoFormat_v410
MP43, // MFVideoFormat_MP43
MP4S, // MFVideoFormat_MP4S
M4S2, // MFVideoFormat_M4S2
MP4V, // MFVideoFormat_MP4V
WMV1, // MFVideoFormat_WMV1
WMV2, // MFVideoFormat_WMV2
WMV3, // MFVideoFormat_WMV3
WVC1, // MFVideoFormat_WVC1
MSS1, // MFVideoFormat_MSS1
MSS2, // MFVideoFormat_MSS2
MPG1, // MFVideoFormat_MPG1
DVSL, // MFVideoFormat_DVSL
DVSD, // MFVideoFormat_DVSD
DVHD, // MFVideoFormat_DVHD
DV25, // MFVideoFormat_DV25
DV50, // MFVideoFormat_DV50
DVH1, // MFVideoFormat_DVH1
DVC, // MFVideoFormat_DVC
H264, // MFVideoFormat_H264
MJPG, // MFVideoFormat_MJPG
YUV_420O, // MFVideoFormat_420O
H263, // MFVideoFormat_H263
H264_ES, // MFVideoFormat_H264_ES
MPEG2, // MFVideoFormat_MPEG2
};
inline e fromGUID(GUID guid)
{
if (guid == MFVideoFormat_RGB32) return RGB32;
else if (guid == MFVideoFormat_ARGB32) return ARGB32;
else if (guid == MFVideoFormat_RGB24) return RGB24;
else if (guid == MFVideoFormat_RGB555) return RGB555;
else if (guid == MFVideoFormat_RGB565) return RGB565;
else if (guid == MFVideoFormat_RGB8) return RGB8;
else if (guid == MFVideoFormat_AI44) return AI44;
else if (guid == MFVideoFormat_AYUV) return AYUV;
else if (guid == MFVideoFormat_YUY2) return YUY2;
else if (guid == MFVideoFormat_YVYU) return YVYU;
else if (guid == MFVideoFormat_YVU9) return YVU9;
else if (guid == MFVideoFormat_UYVY) return UYVY;
else if (guid == MFVideoFormat_NV11) return NV11;
else if (guid == MFVideoFormat_NV12) return NV12;
else if (guid == MFVideoFormat_YV12) return YV12;
else if (guid == MFVideoFormat_I420) return I420;
else if (guid == MFVideoFormat_IYUV) return IYUV;
else if (guid == MFVideoFormat_Y210) return Y210;
else if (guid == MFVideoFormat_Y216) return Y216;
else if (guid == MFVideoFormat_Y410) return Y410;
else if (guid == MFVideoFormat_Y416) return Y416;
else if (guid == MFVideoFormat_Y41P) return Y41P;
else if (guid == MFVideoFormat_Y41T) return Y41T;
else if (guid == MFVideoFormat_Y42T) return Y42T;
else if (guid == MFVideoFormat_P210) return P210;
else if (guid == MFVideoFormat_P216) return P216;
else if (guid == MFVideoFormat_P010) return P010;
else if (guid == MFVideoFormat_P016) return P016;
else if (guid == MFVideoFormat_v210) return v210;
else if (guid == MFVideoFormat_v216) return v216;
else if (guid == MFVideoFormat_v410) return v410;
else if (guid == MFVideoFormat_MP43) return MP43;
else if (guid == MFVideoFormat_MP4S) return MP4S;
else if (guid == MFVideoFormat_M4S2) return M4S2;
else if (guid == MFVideoFormat_MP4V) return MP4V;
else if (guid == MFVideoFormat_WMV1) return WMV1;
else if (guid == MFVideoFormat_WMV2) return WMV2;
else if (guid == MFVideoFormat_WMV3) return WMV3;
else if (guid == MFVideoFormat_WVC1) return WVC1;
else if (guid == MFVideoFormat_MSS1) return MSS1;
else if (guid == MFVideoFormat_MSS2) return MSS2;
else if (guid == MFVideoFormat_MPG1) return MPG1;
else if (guid == MFVideoFormat_DVSL) return DVSL;
else if (guid == MFVideoFormat_DVSD) return DVSD;
else if (guid == MFVideoFormat_DVHD) return DVHD;
else if (guid == MFVideoFormat_DV25) return DV25;
else if (guid == MFVideoFormat_DV50) return DV50;
else if (guid == MFVideoFormat_DVH1) return DVH1;
else if (guid == MFVideoFormat_DVC) return DVC;
else if (guid == MFVideoFormat_H264) return H264;
else if (guid == MFVideoFormat_MJPG) return MJPG;
else if (guid == MFVideoFormat_420O) return YUV_420O;
else if (guid == MFVideoFormat_H263) return H263;
else if (guid == MFVideoFormat_H264_ES) return H264_ES;
else if (guid == MFVideoFormat_MPEG2) return MPEG2;
else return Unknown;
}
inline const char* to_string (const MediaFormat::e& format)
{
switch (format)
{
case RGB32: return "RGB32";
case ARGB32: return "ARGB32";
case RGB24: return "RGB24";
case RGB555: return "RGB555";
case RGB565: return "RGB565";
case RGB8: return "RGB8";
case AI44: return "AI44";
case AYUV: return "AYUV";
case YUY2: return "YUY2";
case YVYU: return "YVYU";
case YVU9: return "YVU9";
case UYVY: return "UYVY";
case NV11: return "NV11";
case NV12: return "NV12";
case YV12: return "YV12";
case I420: return "I420";
case IYUV: return "IYUV";
case Y210: return "Y210";
case Y216: return "Y216";
case Y410: return "Y410";
case Y416: return "Y416";
case Y41P: return "Y41P";
case Y41T: return "Y41T";
case Y42T: return "Y42T";
case P210: return "P210";
case P216: return "P216";
case P010: return "P010";
case P016: return "P016";
case v210: return "v210";
case v216: return "v216";
case v410: return "v410";
case MP43: return "MP43";
case MP4S: return "MP4S";
case M4S2: return "M4S2";
case MP4V: return "MP4V";
case WMV1: return "WMV1";
case WMV2: return "WMV2";
case WMV3: return "WMV3";
case WVC1: return "WVC1";
case MSS1: return "MSS1";
case MSS2: return "MSS2";
case MPG1: return "MPG1";
case DVSL: return "DVSL";
case DVSD: return "DVSD";
case DVHD: return "DVHD";
case DV25: return "DV25";
case DV50: return "DV50";
case DVH1: return "DVH1";
case DVC: return "DVC";
case H264: return "H264";
case MJPG: return "MJPG";
case YUV_420O: return "420O";
case H263: return "H263";
case H264_ES: return "H264_ES";
case MPEG2: return "MPEG2";
default: return "Unknown";
}
}
inline std::ostream& operator<< (std::ostream& os, const MediaFormat::e& format)
{
return os << to_string(format);
}
}
class media_type
{
public:
media_type() : _ptr(NULL)
{
}
media_type(IMFMediaType* ptr) : _ptr(ptr)
{
}
media_type(comet::com_ptr<IMFMediaType> ptr) : _ptr(ptr)
{
}
cv::Size resolution() const
{
UINT32 width, height;
MFGetAttributeSize(_ptr.in(), MF_MT_FRAME_SIZE, &width, &height) | comet::raise_exception;
return cv::Size(width, height);
}
double framerate() const
{
UINT32 num, denom;
MFGetAttributeRatio(_ptr.in(), MF_MT_FRAME_RATE, &num, &denom) | comet::raise_exception;
return static_cast<double>(num) / denom;
}
MediaFormat::e format() const
{
GUID subtype;
_ptr->GetGUID(MF_MT_SUBTYPE, &subtype) | comet::raise_exception;
return MediaFormat::fromGUID(subtype);
}
#ifdef _TYPEDEF_BOOL_TYPE
typedef media_type _Myt;
_TYPEDEF_BOOL_TYPE;
_OPERATOR_BOOL() const _NOEXCEPT
{ // test for non-null pointer
return (_ptr != 0 ? _CONVERTIBLE_TO_TRUE : 0);
}
#else
explicit operator bool() const
{ // test for non-null pointer
return _ptr != 0;
}
#endif
comet::com_ptr<IMFMediaType> _ptr;
};
class camera
{
public:
camera()
{
}
camera(IMFActivate* ptr) : activate_ptr(ptr)
{
}
camera(comet::com_ptr<IMFActivate> ptr) : activate_ptr(ptr)
{
}
// TODO actually implement these or make sure they are deleted/created correctly, this might be the reason for weird mapping of stuff
camera(const camera& other)
{
// this->
// this = other;
}
//= delete;
camera(camera&& other)
{
*this = std::move(other);
}
//camera& operator=(const camera& other) = delete;
camera& operator=(camera&& other)
{
activate_ptr.swap(other.activate_ptr);
source_ptr.swap(other.source_ptr);
reader_ptr.swap(other.reader_ptr);
return *this;
}
~camera()
{
shutdown();
}
bool is_active() const
{
return !source_ptr.is_null();
}
void activate()
{
if (activate_ptr)
activate_ptr->ActivateObject(IID_IMFMediaSource, reinterpret_cast<void**>(source_ptr.out())) | comet::raise_exception;
reader_ptr = NULL;
}
void shutdown()
{
if (activate_ptr)
activate_ptr->ShutdownObject() | comet::raise_exception;
source_ptr = NULL;
reader_ptr = NULL;
}
cv::Mat read_frame(int streamIndex = MF_SOURCE_READER_FIRST_VIDEO_STREAM, int bufferIndex = 0)
{
if (!activate_ptr)
return cv::Mat();
if (!reader_ptr)
{
comet::com_ptr<IMFAttributes> pAttributes;
MFCreateAttributes(pAttributes.out(), 1) | comet::raise_exception;
pAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING, TRUE) | comet::raise_exception;
pAttributes->SetUINT32(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN, TRUE) | comet::raise_exception;
MFCreateSourceReaderFromMediaSource(source_ptr.in(), pAttributes.in(), reader_ptr.out()) | comet::raise_exception;
}
comet::com_ptr<IMFSample> sample;
DWORD actualStreamIndex, flags;
LONGLONG timestamp;
try
{
do
{
reader_ptr->ReadSample(
streamIndex, // Stream index.
0, // Flags.
&actualStreamIndex, // Receives the actual stream index.
&flags, // Receives status flags.
&timestamp, // Receives the time stamp.
sample.out() // Receives the sample or NULL.
) | comet::raise_exception;
} while (sample == NULL && (flags & MF_SOURCE_READERF_STREAMTICK));
}
catch (std::exception& e)
{
std::cerr << "Error getting frame: " << e.what() << std::endl;
std::cerr << " flags: " << flags << std::endl;
shutdown();
activate();
throw;
}
media_type cur_media_type;
reader_ptr->GetCurrentMediaType(actualStreamIndex, cur_media_type._ptr.out()) | comet::raise_exception;
//PrintAttributes(cur_media_type._ptr.in());
auto format = cur_media_type.format();
cv::Mat ret;
DWORD bufCount;
sample->GetBufferCount(&bufCount) | comet::raise_exception;
DWORD bufIndex = bufferIndex >= 0 ? bufferIndex : bufCount - bufferIndex;
if (bufCount > bufIndex)
{
comet::com_ptr<IMFMediaBuffer> buffer;
sample->GetBufferByIndex(bufferIndex, buffer.out()) | comet::raise_exception;
switch (format)
{
case MediaFormat::RGB24:
case MediaFormat::ARGB32:
case MediaFormat::RGB32:
{
comet::com_ptr<IMF2DBuffer> buf2d = try_cast(buffer);
//DWORD length;
//buf2d->GetContiguousLength(&length) | comet::raise_exception;
//ret.create();
//COMET_ASSERT(ret.dataend - ret.datastart == length);
auto resolution = cur_media_type.resolution();
struct buf2d_lock
{
comet::com_ptr<IMF2DBuffer>& buf2d;
buf2d_lock(comet::com_ptr<IMF2DBuffer>& buf2d, BYTE*& scanline0, LONG& pitch) : buf2d(buf2d)
{
buf2d->Lock2D(&scanline0, &pitch) | comet::raise_exception;
}
~buf2d_lock()
{
buf2d->Unlock2D() | comet::raise_exception;
}
};
BYTE *scanline0;
LONG pitch;
buf2d_lock buf_lock_token(buf2d, scanline0, pitch);
if (pitch >= 0)
{
cv::Mat buf2dmat(resolution,
(format == MediaFormat::RGB24) ? CV_8UC3 : CV_8UC4,
scanline0,
pitch);
buf2dmat.copyTo(ret);
}
else
{
cv::Mat buf2dmat(resolution,
(format == MediaFormat::RGB24) ? CV_8UC3 : CV_8UC4,
scanline0 + pitch*(resolution.height-1),
-pitch);
cv::flip(buf2dmat, ret, 0);
}
break;
}
case MediaFormat::MJPG:
{
struct buf_lock
{
comet::com_ptr<IMFMediaBuffer>& buffer;
buf_lock(comet::com_ptr<IMFMediaBuffer>& buffer, BYTE*& data, DWORD& maxLength, DWORD& length) : buffer(buffer)
{
buffer->Lock(&data, &maxLength, &length) | comet::raise_exception;
}
~buf_lock()
{
buffer->Unlock() | comet::raise_exception;
}
};
BYTE* data;
DWORD length;
DWORD maxLength;
buf_lock buf_lock_token(buffer, data, maxLength, length);
ret = cv::imdecode(cv::Mat(length, 1, CV_8U, data), cv::IMREAD_COLOR);
break;
}
default:
std::stringstream sstream;
sstream << "Unknown media format: " << format;
throw std::runtime_error(sstream.str());
}
}
return ret;
}
std::string name() const
{
return get_attr_str(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME);
}
std::string symlink() const
{
return get_attr_str(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK);
}
// TODO change
//explicit operator bool() const
//{
// return !activate_ptr.is_null();
//}
enum Property
{
// CameraControl
Exposure,
Focus,
Zoom,
Pan,
Tilt,
Roll,
Iris,
// VideoProcAmp
Brightness,
Contrast,
Hue,
Saturation,
Sharpness,
Gamma,
ColorEnable,
WhiteBalance,
BacklightCompensation,
Gain
};
bool has(Property property) const;
cam_prop_range get_range(Property property) const;
cam_prop_value get(Property property) const;
void set(Property property, const cam_prop_value& value);
static std::vector<Property> list_properties();
static const char* property_name(Property);
std::vector<media_type> media_types(int streamIndex = 0) const
{
auto pHandler = getMediaTypeHandler(streamIndex);
DWORD cTypes = 0;
pHandler->GetMediaTypeCount(&cTypes) | comet::raise_exception;
std::vector<media_type> ret;
for (DWORD i = 0; i < cTypes; i++)
{
comet::com_ptr<IMFMediaType> pType;
pHandler->GetMediaTypeByIndex(i, pType.out()) | comet::raise_exception;
ret.emplace_back(pType);
}
return ret;
}
media_type get_media_type(int streamIndex = 0)
{
media_type ret;
getMediaTypeHandler(streamIndex)->GetCurrentMediaType(ret._ptr.out()) | comet::raise_exception;
return ret;
}
void set_media_type(const media_type& type, int streamIndex = 0)
{
getMediaTypeHandler(streamIndex)->SetCurrentMediaType(type._ptr.in()) | comet::raise_exception;
if (reader_ptr)
{
reader_ptr->SetCurrentMediaType(streamIndex, nullptr, type._ptr.in()) | comet::raise_exception;
}
}
// TODO change
//explicit operator bool() {
// return !activate_ptr.is_null();
//}
private:
std::string get_attr_str(REFGUID guid) const
{
comet::task_ptr<WCHAR> pStr;
UINT32 strLen;
activate_ptr->GetAllocatedString(guid, pStr.out(), &strLen) | comet::raise_exception;
return comet::bstr_t(pStr.in(), strLen).s_str();
}
comet::com_ptr<IMFMediaTypeHandler> getMediaTypeHandler(int streamIndex = 0) const
{
comet::com_ptr<IMFPresentationDescriptor> pPD;
source_ptr->CreatePresentationDescriptor(pPD.out()) | comet::raise_exception;
BOOL fSelected;
comet::com_ptr<IMFStreamDescriptor> pSD;
pPD->GetStreamDescriptorByIndex(streamIndex, &fSelected, pSD.out()) | comet::raise_exception;
comet::com_ptr<IMFMediaTypeHandler> pHandler;
pSD->GetMediaTypeHandler(pHandler.out()) | comet::raise_exception;
return pHandler;
}
comet::com_ptr<IMFActivate> activate_ptr;
comet::com_ptr<IMFMediaSource> source_ptr;
comet::com_ptr<IMFSourceReader> reader_ptr;
};
class camera_helper
{
public:
static std::vector<camera> get_all_cameras()
{
comet::com_ptr<IMFAttributes> config;
MFCreateAttributes(config.out(), 1) | comet::raise_exception;
config->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID) | comet::raise_exception;
comet::com_ptr_array<IMFActivate> com_ptr_array;
MFEnumDeviceSources(config.in(), com_ptr_array.out(), com_ptr_array.out_count()) | comet::raise_exception;
std::vector<camera> ret;
for (size_t i = 0; i < com_ptr_array.count(); ++i)
{
ret.emplace_back(com_ptr_array[i]);
}
return ret;
}
static camera get_camera_by_symlink(const std::string& symlink)
{
// This is how you should do it, but for some reason it gives an activate pointer with no friendly name
// comet::com_ptr<IMFAttributes> config;
// MFCreateAttributes(config.out(), 1) | comet::raise_exception;
//
// config->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID) | comet::raise_exception;
// comet::bstr_t symlink_bstr(symlink);
// config->SetString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, symlink_bstr.c_str()) | comet::raise_exception;
//
// comet::com_ptr<IMFActivate> activate_ptr;
// MFCreateDeviceSourceActivate(config.in(), activate_ptr.out()) | comet::raise_exception;
//
// return camera(activate_ptr);
for(auto&& camera : get_all_cameras())
{
if (camera.symlink() == symlink)
return std::move(camera);
}
throw std::runtime_error("No camera with symlink: " + std::string(symlink));
}
};
#endif // camera_helper_h__

View file

@ -0,0 +1,150 @@
/** \file
* Array wrapper.
*/
/*
* Copyright © 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*
*/
/*
* comet::array_t is adapted from class array by Nicolai M. Josuttis
*
* (C) Copyright Nicolai M. Josuttis 2001.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*
*/
#ifndef COMET_ARRAY_H
#define COMET_ARRAY_H
#include <cstddef>
#include <stdexcept>
#include <iterator>
#include <algorithm>
#include <vector>
namespace comet {
#pragma pack(push)
#pragma pack(1)
/*!\addtogroup Misc
*/
//@{
template<typename T, size_t SZ> class array_t
{
T a_[SZ];
public:
typedef T value_type;
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
typedef typename std::vector<T>::reverse_iterator reverse_iterator;
typedef typename std::vector<T>::const_reverse_iterator const_reverse_iterator;
typedef typename std::vector<T>::size_type size_type;
typedef typename std::vector<T>::difference_type difference_type;
typedef T& reference;
typedef const T& const_reference;
// reference operator[](size_type i) { return a_[i]; }
// const_reference operator[](size_type i) const { return a_[i]; }
iterator begin() { return iterator(a_); }
iterator end() { return iterator(a_ + SZ); }
const_iterator begin() const { return const_iterator(a_); }
const_iterator end() const { return const_iterator(a_ + SZ); }
reverse_iterator rbegin() { return reverse_iterator(a_); }
reverse_iterator rend() { return reverse_iterator(a_ + SZ); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(a_); }
const_reverse_iterator rend() const { return const_reverse_iterator(a_ + SZ); }
operator const T*() const { return a_; }
operator T*() { return a_; }
static size_type size() { return SZ; }
static bool empty() { return false; }
static size_type max_size() { return SZ; }
enum { static_size = SZ };
reference front() { return a_[0]; }
const_reference front() const { return a_[0]; }
reference back() { return a_[SZ-1]; };
const_reference back() const { return a_[SZ-1]; }
// swap (note: linear complexity)
void swap (array_t<T,SZ>& y) {
std::swap_ranges(begin(),end(),y.begin());
}
// assignment with type conversion
template <typename T2>
array_t<T,SZ>& operator= (const array_t<T2,SZ>& rhs) {
std::copy(rhs.begin(),rhs.end(), begin());
return *this;
}
// assign one value to all elements
void assign (const T& value)
{
std::fill_n(begin(),size(),value);
}
reference at(size_type i) { rangecheck(i); return a_[i]; }
const_reference at(size_type i) const { rangecheck(i); return a_[i]; }
private:
// check range (may be private because it is static)
static void rangecheck (size_type i) {
if (i >= size()) { throw std::range_error("array"); }
}
};
//@}
#pragma pack(pop)
// comparisons
template<class T, size_t SZ>
bool operator== (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return std::equal(x.begin(), x.end(), y.begin());
}
template<class T, size_t SZ>
bool operator< (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
}
template<class T, size_t SZ>
bool operator!= (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return !(x==y);
}
template<class T, size_t SZ>
bool operator> (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return y<x;
}
template<class T, size_t SZ>
bool operator<= (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return !(y<x);
}
template<class T, size_t SZ>
bool operator>= (const array_t<T,SZ>& x, const array_t<T,SZ>& y) {
return !(x<y);
}
}
#endif

View file

@ -0,0 +1,68 @@
/** \file
Provide run-time asserts.
*/
/*
* Copyright © 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ASSERT_H
#define COMET_ASSERT_H
#include <stdexcept>
# if defined(COMET_ASSERT_THROWS) || defined(COMET_ASSERT_THROWS_ALWAYS)
# if defined(COMET_ASSERT_THROWS_ALWAYS) || !defined(NDEBUG)
namespace comet
{
/*! \defgroup ErrorHandling Error handling.
*/
//@{
//! Indicates a comet assertion failed.
/** This is enabled for debug builds if COMET_ASSERT_THROWS is defined and
* enabled for both debug and release if COMET_ASSERT_THROWS_ALWAYS is defined.
*/
struct assert_failed : std::runtime_error
{
assert_failed( const char *val) : runtime_error(val) {}
};
//@}
}
# define COMET_ASSERT(x_) if (x_) ; else throw comet::assert_failed("Assert Failed: " #x_ );
# define COMET_THROWS_ASSERT throw( comet::assert_failed)
# else
# define COMET_ASSERT(x_) ;
# endif
# else
# define COMET_THROWS_ASSERT throw()
# ifndef __CYGWIN__
# include <crtdbg.h>
# define COMET_ASSERT _ASSERTE
# else
# include <assert.h>
# define COMET_ASSERT assert
# endif
# endif
/*! \addtogroup ErrorHandling
*/
//@{
/** \def COMET_ASSERT Assertion in commet.
* \sa COMET_THROWS_ASSERT COMET_ASSERT_THROWS_ALWAYS
*/
//@}
#endif

View file

@ -0,0 +1,121 @@
/** \file
* ATL Module Compatability wrapper.
*/
/*
* Copyright © 2000, 2001 Paul Hollingsworth, Michael Geddes
* Copyright © 2013 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ATL_MODULE_H
#define COMET_ATL_MODULE_H
#include <comet/server.h>
#include <atlbase.h>
namespace comet {
/*! \defgroup ATL ATL conversion.
*/
//@{
/** \struct declspec_comtype atl_module.h comet/atl_module.h
* Helper to create a 'comtype' for a non-comet interface.
* \code
* namespace comet{
* template<> struct comtype<IApplicationOption> :
* declspec_comtype<IApplicationOption, ::IDispatch >
* { };
* };
* \endcode
*
*/
template<typename ITF, typename BASE = ::IUnknown> struct declspec_comtype
{
static const uuid_t& uuid() { return uuid_t::create_const_reference(__uuidof(ITF)); }
typedef BASE base;
};
/// Placeholder for an empty comet typelibrary.
struct empty_typelib
{
typedef nil coclasses;
};
template<typename COM_SERVER, typename ATL_MODULE = ATL::CComModule>
class atl_module_ex : public ATL_MODULE
{
// ATL will take the responsibility of registering the embedded type library.
public:
HRESULT Init(_ATL_OBJMAP_ENTRY* p, HINSTANCE h, const GUID* plibid = NULL)
{
module().instance(h);
return ATL_MODULE::Init(p, h, plibid);
}
HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID* pCLSID = NULL)
{
HRESULT hr = ATL_MODULE::RegisterServer(bRegTypeLib, pCLSID);
if(SUCCEEDED(hr))
hr = COM_SERVER::DllRegisterServer();
return hr;
}
HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID* pCLSID = NULL)
{
COM_SERVER::DllUnregisterServer();
return ATL_MODULE::UnregisterServer(bUnRegTypeLib, pCLSID);
}
HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
HRESULT hr = COM_SERVER::DllGetClassObject( rclsid, riid, ppv);
if( hr == CLASS_E_CLASSNOTAVAILABLE )
{
hr = ATL_MODULE::GetClassObject(rclsid, riid,ppv);
}
return hr;
}
LONG GetLockCount()
{
return module().rc() + ATL_MODULE::GetLockCount();
}
};
/** Wraps an ATL::CComModule to provide co-existing ATL/Comet co-classes.
* ATL will take responsibility for registering the embedded type-library.
*
* Here is an example of how to use it:
* \code
* struct typelib_subset
* {
* typedef COMET_STRICT_TYPENAME comet::typelist::make_list< CoClass1, CoClass2 > coclasses;
* };
* comet::atl_module<typelib_subset> _Module;
* \endcode
* And in std.h:
* \code
* struct typelib_subset;
* extern comet::atl_module<typelib_subset> _Module;
* \endcode
*/
template<typename TYPELIB = empty_typelib, typename ATL_MODULE = ATL::CComModule>
class atl_module : public atl_module_ex< com_server<TYPELIB, com_server_traits<NO_EMBEDDED_TLB> >, ATL_MODULE >
{
};
//@}
} // namespace comet
#endif

View file

@ -0,0 +1,99 @@
/** \file
* Simple uncopyable buffer class.
*/
/*
* Copyright © 2004, Michael Geddes, Lijun Qin.
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef INCLUDE_COMET_AUTO_BUFFER_H
#define INCLUDE_COMET_AUTO_BUFFER_H
#ifdef _SHOW_INC
#pragma message(" #Include " __FILE__)
#endif
namespace comet
{
/*!\addtogroup Misc
*/
//@{
/** \class auto_buffer_t auto_buffer.h comet/auto_buffer.h
* Simle auto-deleting buffer class.
* Non-copyable /returnable.
*/
template <typename T>
class auto_buffer_t
{
public:
typedef size_t size_type;
/** Create a buffer of the given size.
* This is the only valid constructor.
*/
explicit auto_buffer_t(size_type size)
{
begin_ = new T[size];
}
/// Auto-delete the buffer.
~auto_buffer_t() throw() { delete[] begin_; }
/// Clear the buffer.
void clear() throw()
{
delete[] begin_;
begin_ = 0;
}
/// Is the buffer empty.
bool empty() const throw()
{
return begin_ != NULL;
}
/// Resize the buffer.
void resize( size_type newSize) throw()
{
delete[] begin_;
begin_ = new T[newSize];
}
/// Return a reference to the specifed element.
T & at( size_type t) throw() { return begin_[t]; }
T & operator[]( size_type t) throw() { return begin_[t]; }
/// Return a const reference to the specifed element.
const T & at( size_type t) const throw() { return begin_[t]; }
const T & operator[]( size_type t) const throw() { return begin_[t]; }
/// Detatch the memory.
T *detach()
{
T *val = begin_;
begin_ = NULL;
return val;
}
/// Return the memory.
T *get() { return begin_; }
const T *get()const { return begin_; }
private:
/// Can't assign.
auto_buffer_t &operator=(const auto_buffer_t &);
/// can't copy.
auto_buffer_t(const auto_buffer_t&);
/// Pointer to memory.
T *begin_;
};
//@}
}
#endif /* INCLUDE_COMET_AUTO_BUFFER_H */

View file

@ -0,0 +1,948 @@
/** \file
* BSTR wrapper classes.
*/
/*
* Copyright © 2000-2004 Sofus Mortensen, Michael Geddes
* Copyright © 2012 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_BSTR_H
#define COMET_BSTR_H
#include <comet/config.h>
#ifdef COMET_BROKEN_WTYPES
#include <windows.h>
#endif // COMET_BROKEN_WTYPES
#include <wtypes.h>
#include <malloc.h>
#include <stdexcept>
#ifndef COMET_GCC_HEADERS
#include <oleauto.h>
#endif // COMET_GCC_HEADERS
#include <string>
#include <functional>
#undef max
#include <limits>
#include <comet/assert.h>
#include <comet/common.h>
#include <comet/static_assert.h>
#include <comet/error_fwd.h>
#include <comet/uuid_fwd.h>
#include <comet/currency.h>
#include <comet/type_traits.h>
#pragma warning(push)
#pragma warning(disable : 4522 4521)
#pragma comment( lib, "oleaut32" )
namespace comet {
#ifndef NORM_IGNOREKASHIDA
#define NORM_IGNOREKASHIDA 0x00040000
#endif // NORM_IGNOREKASHIDA
/*! \addtogroup COMType
*/
//@{
//! Comparsion flags.
/*! Can be used with \link comet::bstr_t::cmp cmp \endlink or the comparsion functors.
\sa cmp
less
less_equal
greater
greater_equal
equal_to
not_equal_to
*/
enum compare_flags_t
{
cf_ignore_case = NORM_IGNORECASE, //!< Ignore case.
cf_ingore_nonspace = NORM_IGNORENONSPACE, //!< Ignore nonspacing chars.
cf_ignore_symbols = NORM_IGNORESYMBOLS, //!< Ignore symbols.
cf_ignore_width = NORM_IGNOREWIDTH, //!< Ignore string width.
cf_ignore_kanatype = NORM_IGNOREKANATYPE, //!< Ignore Kana type.
cf_ignore_kashida = NORM_IGNOREKASHIDA //!< Ignore Arabic kashida characters.
};
//@}
namespace impl {
inline const wchar_t* null_to_empty(const wchar_t* s)
{ return s ? s : L""; }
} // namespace
/*! \addtogroup COMType
*/
//@{
/*! \class bstr_t bstr.h comet/bstr.h
* BSTR Wrapper.
* \sa bstr_t
*/
class bstr_t {
public:
typedef wchar_t value_type;
#if !(defined(_STLP_DEBUG) || (defined(_HAS_ITERATOR_DEBUGGING)) && _MSC_VER >= 1400)
typedef std::wstring::iterator iterator;
typedef std::wstring::const_iterator const_iterator;
typedef std::wstring::reverse_iterator reverse_iterator;
typedef std::wstring::const_reverse_iterator const_reverse_iterator;
#else // _STLP_DEBUG
typedef wchar_t *iterator;
typedef const wchar_t *const_iterator;
#if defined(COMET_STD_ITERATOR)
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#else
// workaround for broken reverse_iterator implementations due to no partial specialisation
typedef std::reverse_iterator<iterator,wchar_t> reverse_iterator;
typedef std::reverse_iterator<const_iterator,wchar_t> const_reverse_iterator;
#endif
#endif // _STLP_DEBUG
typedef std::wstring::size_type size_type;
typedef std::wstring::difference_type difference_type;
typedef wchar_t& reference;
typedef const wchar_t const_reference;
private:
BSTR str_;
void construct() { str_ = 0; }
void construct(BSTR s, bool copy) throw(std::bad_alloc)
{ if (copy) str_ = copy_str(s); else str_ = s; }
void construct(const wchar_t* s) throw(std::bad_alloc)
{ str_ = copy_str(s); }
void construct(const wchar_t* s, size_t len) throw(std::bad_alloc)
{ str_ = copy_str(s, len); }
void construct(const char* s) throw(std::bad_alloc, std::runtime_error) {
convert_str(s, -1);
}
void construct(const char* s, size_t len)
{
if (len >= static_cast<size_t>(std::numeric_limits<int>::max()))
throw std::length_error(
"String exceeded maximum length for conversion");
convert_str(s, static_cast<int>(len+1));
}
void construct(const uuid_t& u, bool braces)
{
str_ = impl::bad_alloc_check(::SysAllocStringLen(0, braces?38:36));
u.copy_to_str(str_+(braces?1:0));
if (braces)
{
str_[0]=L'{';
str_[37]=L'}';
}
}
void construct(const wchar_t* s1, size_t l1, const wchar_t* s2, size_t l2) throw(std::bad_alloc)
{
str_ = impl::bad_alloc_check(::SysAllocStringLen(NULL, UINT(l1+l2)));
if (l1) memcpy(str_, s1, sizeof(wchar_t)*(l1));
if (l2) memcpy(str_+l1, s2, sizeof(wchar_t)*(1+l2));
}
void destroy() throw()
{ if (str_) ::SysFreeString(str_); }
bool is_regular() const throw()
{ return !str_ || length() == wcslen(str_); }
static BSTR copy_str(const wchar_t* src) throw(std::bad_alloc)
{ return src ? impl::bad_alloc_check(::SysAllocString(src)) : 0; }
static BSTR copy_str(const wchar_t* src, size_t len) throw(std::bad_alloc)
{ return src ? impl::bad_alloc_check(::SysAllocStringLen(src, UINT(len))) : 0; }
static BSTR copy_str(BSTR src) throw(std::bad_alloc)
{ return src ? impl::bad_alloc_check(::SysAllocStringLen(src, ::SysStringLen(src))) : 0; }
void convert_str(const char* s, int l) throw(std::bad_alloc, std::runtime_error)
{
if (s != 0) {
#if defined(_MBCS) || !defined(COMET_NO_MBCS)
int wl = ::MultiByteToWideChar(CP_ACP, 0, s, l, NULL,0);
#else
int wl = ((l>=0)?l: (1+strlen(s)));
COMET_ASSERT( wl == ::MultiByteToWideChar( CP_ACP, 0, s, l, NULL,0));
#endif
str_ = impl::bad_alloc_check(::SysAllocStringLen(0, wl - 1));
if (::MultiByteToWideChar(CP_ACP, 0, s, l, str_, wl) == 0)
{
destroy();
throw std::runtime_error("MultiByteToWideChar has failed");
}
} else str_ = 0;
}
public:
/*! Default constructor
Constructs a null string.
*/
bstr_t() throw()
{
construct();
}
//! Copy constructor
/*!
\param s
String initialise bstr_t from.
\exception std::bad_alloc
On memory exhaustion std::bad_alloc is thrown.
*/
bstr_t(const bstr_t& s) throw(std::bad_alloc)
{
construct(s.str_, true);
}
//! Construct string from const wchar_t*
/*!
\param s
String to initialise bstr_t from.
\exception std::bad_alloc
On memory exhaustion std::bad_alloc is thrown.
*/
bstr_t(const wchar_t* s) throw(std::bad_alloc)
{
construct(s);
}
bstr_t(const wchar_t* s, size_t len) throw(std::bad_alloc)
{
construct(s, len);
}
//! Construct string from const char*
/*!
\param s
String to initialise bstr_t from.
\exception std::bad_alloc
On memory exhaustion std::bad_alloc is thrown.
\exception std::runtime_error
Should string conversion fail, std::runtime_error will be thrown.
*/
bstr_t(const char* s) throw(std::runtime_error)
{
construct(s);
}
bstr_t(const char* s, size_t len) throw(std::bad_alloc)
{
construct(s, len);
}
//! Construct string from const std::string&
/*!
\param s
String to initialise bstr_t from.
\exception std::bad_alloc
On memory exhaustion std::bad_alloc is thrown.
\exception std::length_error
If this given string is too long to be converted,
std::length_error is thrown.
\exception std::runtime_error
Should string conversion fail, std::runtime_error is thrown.
*/
bstr_t(const std::string& s)
{
construct(s.c_str(), s.length());
}
//! Construct string from BSTR
/*!
Takes ownership of specified BSTR. To prevent misuse the BSTR must be wrapped using auto_attach.
\code
bstr_t bs( auto_attach( myBSTR ) );
\endcode
\param s
String to initialise bstr_t from.
*/
bstr_t(const impl::auto_attach_t<BSTR>& s) throw()
{
construct(s.get(), false);
}
//! Construct string from const std::wstring&
/*!
\param s
String to initialise bstr_t from.
\exception std::bad_alloc
On memory exhaustion std::bad_alloc is thrown.
*/
bstr_t(const std::wstring& s) throw(std::bad_alloc)
{
construct(s.c_str(), s.length());
}
explicit bstr_t(size_type sz, wchar_t c) throw(std::bad_alloc)
{
str_ = impl::bad_alloc_check(::SysAllocStringLen(0, UINT(sz)));
std::fill(begin(), end(), c);
}
explicit bstr_t(size_type sz) throw(std::bad_alloc)
{
str_ = impl::bad_alloc_check(::SysAllocStringLen(0, UINT(sz)));
}
template<typename IT>
explicit bstr_t(IT first, IT last)
{
str_ = 0;
assign(first, last);
}
explicit bstr_t(const uuid_t& u, bool braces = false)
{
construct(u, braces);
}
private:
bstr_t(const wchar_t* s1, size_t l1, const wchar_t* s2, size_t l2) throw(std::bad_alloc)
{
construct(s1, l1, s2, l2);
}
public:
//! Destructor
/*!
Deletes the wrapped BSTR.
*/
~bstr_t() throw()
{
destroy();
}
//! Swap
void swap(bstr_t& x) throw()
{
std::swap(str_, x.str_);
}
//! Explicit conversion to const wchar_t*
const wchar_t* c_str() const throw()
{ return impl::null_to_empty(str_); }
//! Explicit conversion to std::wstring
std::wstring w_str() const throw()
{ return impl::null_to_empty(str_); }
#ifdef _MBCS
#ifndef COMET_NO_MBCS_WARNING
#pragma message( "Warning: _MBCS is defined. bstr_t::s_str may return an std::string containing multibyte characters" )
#endif
#endif
//! Explicit conversion to std::string
std::string s_str() const
{
if (is_empty()) return std::string();
if (length() > static_cast<size_t>(std::numeric_limits<int>::max()))
throw std::length_error("String is too large to be converted");
int ol = static_cast<int>(length());
#if defined(_MBCS) || !defined(COMET_NO_MBCS)
// Calculate the required length of the buffer
int l = WideCharToMultiByte(CP_ACP, 0, str_, ol, NULL, 0, NULL, NULL);
#else // _MBCS
int l = ol;
COMET_ASSERT( l == WideCharToMultiByte(CP_ACP, 0, str_, ol, NULL, 0, NULL, NULL));
#endif // _MBCS
// Create the buffer
std::string rv(l, std::string::value_type());
// Do the conversion.
if (0 == WideCharToMultiByte(
CP_ACP, 0, str_, ol, &rv[0], l, NULL, NULL))
{
DWORD err = GetLastError();
raise_exception(HRESULT_FROM_WIN32(err));
}
return rv;
}
//! Explicit conversion to "tstring".
#ifdef _UNICODE
std::wstring t_str() const
{
return w_str();
}
#else
std::string t_str() const
{
return s_str();
}
#endif
//! Implicit conversion to std::wstring
operator std::wstring() const { return w_str(); }
//! Implicit conversion to std::string
operator std::string() const { return s_str(); }
//! Returns true if and only if wrapped str is null
bool is_null() const throw()
{ return str_ == 0; }
/** Returns true if and only if wrapped str has zero length.
*/
bool is_empty() const throw() { return length() == 0; }
//! Returns true if and only if wrapped str has zero length.
bool empty() const throw() { return length() == 0; }
//! Returns length of wrapped string.
size_t length() const throw()
{ return is_null() ? 0 : ::SysStringLen(str_); }
size_t size() const throw()
{ return length(); }
/*! \internal */
BSTR get_raw() const
{ return str_; }
friend
std::basic_ostream<char> &operator<<(std::basic_ostream<char> &os, const bstr_t &val)
{ os << val.s_str(); return os; }
friend
std::basic_ostream<wchar_t> &operator<<(std::basic_ostream<wchar_t> &os, const bstr_t &val)
{ os << val.w_str(); return os; }
/// \name Boolean operators
//@{
bool operator==(const wchar_t* s) const
{ return 0 == wcscmp(c_str(), impl::null_to_empty(s) ) && is_regular(); }
bool operator!=(const wchar_t* s) const
{ return !operator==(s); }
bool operator<(const wchar_t* s) const
{ return wcscmp(c_str(), impl::null_to_empty(s)) < 0 && is_regular(); }
bool operator>(const wchar_t* s) const
{ return wcscmp(c_str(), impl::null_to_empty(s)) > 0 && !is_regular(); }
bool operator>=(const wchar_t* s) const
{ return !operator<(s); }
bool operator<=(const wchar_t* s) const
{ return !operator>(s); }
bool operator==(const std::wstring& s) const
{
size_t l = length();
if (l != s.length()) return false;
return 0 == memcmp(str_, s.c_str(), sizeof(wchar_t)*l);
}
bool operator!=(const std::wstring& s) const
{ return !operator==(s); }
bool operator<(const std::wstring& s) const
{ return std::lexicographical_compare(str_, str_+length(), s.begin(), s.end()); }
bool operator>(const std::wstring& s) const
{ return std::lexicographical_compare(str_, str_+length(), s.begin(), s.end(), std::greater<wchar_t>()); }
bool operator>=(const std::wstring& s) const
{ return !operator<(s); }
bool operator<=(const std::wstring& s) const
{ return !operator>(s); }
bool operator==(const bstr_t& s) const
{
if (str_ == 0 && s.str_ == 0) return true;
return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_EQ;
}
bool operator!=(const bstr_t& s) const
{ return !operator==(s); }
bool operator<(const bstr_t& s) const
{
if (str_ == 0) {
return s.str_ != 0;
}
if (s.str_ == 0) return false;
return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_LT;
}
bool operator>(const bstr_t& s) const
{
if (str_ == 0) {
return s.str_ != 0;
}
if (s.str_ == 0) return false;
return ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), 0) == VARCMP_GT;
}
bool operator>=(const bstr_t& s) const
{ return !operator<(s); }
bool operator<=(const bstr_t& s) const
{ return !operator>(s); }
//@}
//! String comparsion function.
/*! \param s String to compare
\param flags Comparison Flags
\retval &lt;0 if less
\retval 0 if Equal
\retval &gt;0 if greater
*/
int cmp(const bstr_t& s, compare_flags_t flags = compare_flags_t(0)) const
{
HRESULT res = ::VarBstrCmp(str_, s.str_, ::GetThreadLocale(), flags);
switch(res)
{
case VARCMP_EQ: return 0;
case VARCMP_GT: return 1;
case VARCMP_LT: return -1;
case VARCMP_NULL:
return ((str_==0)?0:1) - ((s.str_==0)?0:1);
}
if (str_==0 || s.str_ ==0)
return ((str_==0)?0:1) - ((s.str_==0)?0:1);
raise_exception(res); return 0;
}
//!\name Comparison Functors
//@{
//! Less Functor.
/*! Useful for STL containers.
\code
typedef stl::map < comet::bstr_t, long, bstr_t::less<cf_ignore_case> > string_long_map;
\endcode
\param CF comparison flags.
\relates bstr_t
*/
template<compare_flags_t CF>
struct less : std::binary_function< bstr_t,bstr_t,bool>{
/// Functor.
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) <0; }
};
//! less or equal functor.
/*! \relates bstr_t */
template<compare_flags_t CF>
struct less_equal : std::binary_function< bstr_t,bstr_t,bool> {
/// Functor.
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) <=0; }
};
//! greater functor.
/*! \relates bstr_t */
template<compare_flags_t CF>
struct greater : std::binary_function< bstr_t,bstr_t,bool> {
/// Functor.
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) > 0; }
};
//! greater or equal functor.
/*! \relates bstr_t */
template<compare_flags_t CF>
struct greater_equal : std::binary_function< bstr_t,bstr_t,bool> {
/// Functor.
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) >=0; }
};
//! equality functor.
template<compare_flags_t CF>
struct equal_to : std::binary_function< bstr_t,bstr_t,bool> {
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) == 0; }
};
//! Inequality functor.
/*! \relates bstr_t */
template<compare_flags_t CF>
struct not_equal_to : std::binary_function< bstr_t,bstr_t,bool>{
/// Functor.
bool operator()(const bstr_t& l, const bstr_t& r) const
{ return l.cmp(r, CF) != 0; }
};
//@}
iterator begin() { return iterator(str_); }
iterator end() { return iterator(str_ + length()); }
const_iterator begin() const { return const_iterator(str_); }
const_iterator end() const { return const_iterator(str_ + length()); }
reverse_iterator rbegin() { return reverse_iterator(str_); }
reverse_iterator rend() { return reverse_iterator(str_ + length()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(str_); }
const_reverse_iterator rend() const { return const_reverse_iterator(str_ + length()); }
reference at(size_type i) { rangecheck(i); return str_[i]; }
const_reference at(size_type i) const { rangecheck(i); return str_[i]; }
private:
// check range (may be private because it is static)
void rangecheck (size_type i) const {
if (i >= length()) { throw std::range_error("bstr_t"); }
}
public:
const_reference operator[](size_type idx) const
{ return str_[idx]; }
reference operator[](size_type idx)
{ return str_[idx]; }
//! Assign string to be \p sz of character \p c .
void assign(size_type sz, wchar_t c) throw(std::bad_alloc)
{
bstr_t t(sz, c);
swap(t);
}
//! Assign string from two iterators.
template<typename IT>
void assign(IT first, IT last)
{
bstr_t t( std::distance(first, last) );
#pragma warning(push)
#pragma warning(disable:4996)
std::copy(first, last, t.begin());
#pragma warning(pop)
swap(t);
}
//! Assignment operator from any (non integer) constructable.
template<typename T>
bstr_t& operator=(const T& x)
{
COMET_STATIC_ASSERT( type_traits::is_integer<T>::result == false );
bstr_t t(x);
swap(t);
return *this;
}
//! Default assignment.
bstr_t& operator=(const bstr_t& x) throw(std::bad_alloc)
{
bstr_t t(x);
swap(t);
return *this;
}
//! Concat operation
bstr_t operator+(const bstr_t& s) const throw(std::bad_alloc)
{
return bstr_t(str_, length(), s.str_, s.length());
}
//! Concat with const wchar_t*
bstr_t operator+(const wchar_t* s) const throw(std::bad_alloc)
{
return bstr_t(str_, length(), s, wcslen(s));
}
//! Concat with std::wstring
bstr_t operator+(const std::wstring& s) const throw(std::bad_alloc)
{
return bstr_t(str_, length(), s.c_str(), s.length());
}
//! Concat assignment
bstr_t& operator+=(const bstr_t& s) throw(std::bad_alloc)
{
bstr_t t(str_, length(), s.str_, s.length());
swap(t);
return *this;
}
//! Concat assignment with const wchar_t*
bstr_t& operator+=(const wchar_t* s) throw(std::bad_alloc)
{
bstr_t t(str_, length(), s, wcslen(s));
swap(t);
return *this;
}
//! Concat assignment with std::wstring
bstr_t& operator+=(const std::wstring& s) throw(std::bad_alloc)
{
bstr_t t(str_, length(), s.c_str(), s.length());
swap(t);
return *this;
}
// Detach a raw BSTR from it's wrapper - detach function is dangerous.
BSTR detach()
{
BSTR s(str_);
str_ = 0;
return s;
}
public:
//!\name Create a reference to a BSTR
/*!
Creates a bstr_t that is a reference to the BSTR.
It will not be reference counted and will not be deleted when the bstr_t goes out of scope.
This is used by the interface wrappers for [in] BSTR's. Typically clients do not need create_reference.
*/
//@{
static const bstr_t& create_const_reference(const BSTR& s) throw()
{ return *reinterpret_cast<const bstr_t*>(&s); }
static bstr_t& create_reference(BSTR& s) throw()
{ return *reinterpret_cast<bstr_t*>(&s); }
//@}
//! Detaches specified bstr
static BSTR detach(bstr_t& s)
{
return s.detach();
}
/*! \internal */
template<typename T>
static BSTR detach(const T& s)
{
return bstr_t(s).detach();
}
/*! \internal */
BSTR* get_ptr_to_raw() const
{
return const_cast<BSTR*>(&str_);
}
//! [in] adapter.
/*!
Used when calling raw interfaces that require an [in] BSTR argument.
\code
bstr_t bs;
HRESULT hr = pRawInterface->raw_Method(bs.in());
\endcode
Only use this wrapper when forced to deal with raw interface.
*/
BSTR in() const throw()
{
return str_;
}
//! [in] adapter.
/*!
Used when calling raw interfaces that require an [in] BSTR* argument.
\code
bstr_t bs;
HRESULT hr = pRawInterface->raw_Method(bs.in_ptr());
\endcode
Only use this wrapper when forced to deal with raw interface.
*/
BSTR* in_ptr() const throw()
{
return const_cast<BSTR*>(&str_);
}
//! [out] adapter.
/*!
Used when calling raw interfaces that require an [out] BSTR * argument.
\code
bstr_t bs;
HRESULT hr = pRawInterface->raw_MethodThatReturnsBSTR(bs.out());
\endcode
Only use this wrapper when forced to deal with raw interface.
*/
BSTR* out() throw()
{
destroy();
return &str_;
}
//! [in, out] adapter.
/*!
Used when calling raw interfaces that require an [in, out] BSTR * argument.
\code
bstr_t bs;
HRESULT hr = pRawInterface->raw_MethodThatChangesBSTR(bs.inout());
\endcode
Only use this wrapper when forced to deal with raw interface.
\note If the wrapped BSTR is shared. The bstr_t is copied so that only this version is modified.
\exception std::bad_alloc
Throws std::bad_alloc if the bstr_t is being copied and memory is exhausted.
*/
BSTR* inout() throw(std::bad_alloc)
{
return &str_;
}
friend bstr_t operator+(const std::wstring& s, const bstr_t& t) throw(std::bad_alloc);
friend bstr_t operator+(const wchar_t* s, const bstr_t& t) throw(std::bad_alloc);
};
//! Concat operation
inline bstr_t operator+(const std::wstring& s, const bstr_t& t) throw(std::bad_alloc)
{
return bstr_t(s.c_str(), s.length(), t.str_, t.length());
}
//! Concat operation
inline bstr_t operator+(const wchar_t* s, const bstr_t& t) throw(std::bad_alloc)
{
return bstr_t(s, wcslen(s), t.str_, t.length());
}
//@}
/*! \name Boolean Operators on String
* \relates bstr_t
*/
//@{
inline bool operator==(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 == s1;
}
inline bool operator!=(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 != s1;
}
inline bool operator<(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 > s1;
}
inline bool operator>(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 < s1;
}
inline bool operator<=(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 >= s1;
}
inline bool operator>=(const wchar_t* s1, const bstr_t& s2) throw()
{
return s2 <= s1;
}
inline bool operator==(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 == s1;
}
inline bool operator!=(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 != s1;
}
inline bool operator<(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 > s1;
}
inline bool operator>(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 < s1;
}
inline bool operator<=(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 >= s1;
}
inline bool operator>=(const std::wstring& s1, const bstr_t& s2) throw()
{
return s2 <= s1;
}
//@}
// Implementation of uuid_t construct from bstr.
inline uuid_t::uuid_t(const bstr_t& bs)
{
if (init_from_str(bs.c_str(), bs.length()) == false) throw std::runtime_error(err_msg());
}
inline currency_t& currency_t::parse( const bstr_t &str, LCID locale )
{
VarCyFromStr( str.in(), locale, 0, &cy_ ) | raise_exception;
return *this;
}
} // namespace
namespace {
COMET_STATIC_ASSERT( sizeof(comet::bstr_t) == sizeof(BSTR) );
COMET_STATIC_ASSERT( sizeof(comet::bstr_t) == sizeof(BSTR) );
}
namespace std {
template<> inline void swap( comet::bstr_t& x, comet::bstr_t& y) COMET_STD_SWAP_NOTHROW { x.swap(y); }
}
#include <comet/uuid.h>
#pragma warning(pop)
#endif /* COMET_BSTR_H */

View file

@ -0,0 +1,628 @@
/** \file
* Provide logging for calls.
*/
/*
* Copyright © 2003 Michael Geddes
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_CALLLOG_H
#define COMET_CALLLOG_H
#include <comet/config.h>
#include <comet/tstring.h>
#include <comet/variant.h>
#include <comet/currency.h>
#include <comet/server.h>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <comet/handle_except.h>
/** \page cometcalllogging Call Logging
This is a feature of the comet interfaces that allows the server to log all
calls to any of the interface methods. It logs parameter values, and also allows
logging of errors (see \ref comethandleexception ).
Call logging in comet is enabled by using <kbd>tlb2h -L</kbd> (see \ref tlb2husage).
To enable logging to a specified file, define COMET_LOGFILE and define
COMET_LOGFILE_DEFAULT to be the required logfile (see comet::stream_call_logger_t).
To override logging, specialise comet::call_logger_<true> and implement all the interfaces
defined by the default comet::call_logger_.
How various parameter types are output can be modified by specialising the
function comet::comet_log.
*/
/** \defgroup CallLog Call-logging
*@{
*/
#ifdef COMET_DOXYGEN // Only for doxygen
/** \def COMET_LOGFILE
* Define to get simple interface logfiles.
* Must use tlb2h -L to enable interface logging. See \ref tlb2husage.
* \sa comet_log comet_log_interface comet_log_array stream_call_logger_t tofstream_comet
*/
#define COMET_LOGFILE
/** \def COMET_LOGFILE_DEFAULT
* If COMET_LOGFILE is defined, define to set the default logfile name.
* \code
#define COMET_LOGFILE_DEFAULT "C:\\log\\comet.log"
* \endcode
* \relates call_logger_
*/
#define COMET_LOGFILE_DEFAULT "C:\\log\\comet.log"
#endif // COMET_DOXYGEN
//@}
namespace comet
{
/*!\addtogroup CallLog
*/
//@{
/** \struct call_logger_ calllog.h comet/calllog.h
* Default NULL logger and description of 'call logger' concept.
* Specialise to \b true to override.
* \code
template<>
struct call_logger_<true> : stream_call_logger_t<tofstream_comet>
{
};
* \endcode
* \sa stream_call_logger_t tofstream_comet
*/
template<bool OVERRIDE>
struct call_logger_
{
/** Should the call be logged?
* \return Return true to allow call to be logged.
*/
static inline bool can_log_call() { return false; }
/** Should the return values be logged?
* \return Return true to allow call return values to be logged.
*/
static inline bool can_log_return() { return false; }
/** Called by interfaces to provide call logging.
*/
static inline void log_call( const tstring &iface, const tstring &funcname, const tstring &log){}
/// Called by interfaces to provide call return logging.
static inline void log_return( const tstring &iface, const tstring &funcname, const tstring &log, const tstring &retval){}
///\name Exception handling redirection.
//@{
/** Should the error be logged?
* \return Return true to allow error to be logged.
*/
static inline bool can_log_exception() { return false; }
/// Called by exception handlers to provide logging for errors.
static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource ,const source_info_t &callSource ){}
//@}
};
/** \struct stream_call_logger_t calllog.h comet/calllog.h
* Log calls to a tostream.
* A class/struct that subscribes to and implements the 'call logger' concept for a steam.
* Template paramter is expected to be a class that has a method that creates a tostream
* instance as follows:
* \code
* static tostream *create()
* \endcode
* \param CREATESTREAM Class with a static function \p create() that returns a <b> tostream * </b>
* \sa tofstream_comet call_logger_
*/
template<typename CREATESTREAM>
struct stream_call_logger_t
#ifdef COMET_DOXYGEN // For documentation
: call_logger_
#endif
{
static inline bool can_log_call()
{
tostream *ofs = logger();
return ofs != NULL && ofs->good();
}
static inline bool can_log_return() { return can_log_call(); }
static inline bool can_log_exception() { return can_log_call(); }
static inline void log_call( const tstring &iface, const tstring &funcname, const tstring &log)
{
log_( false, iface, funcname, log, tstring());
}
static inline void log_return( const tstring &iface, const tstring &funcname, const tstring &log, const tstring &retval)
{
log_( true, iface, funcname, log, retval);
}
static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource ,const source_info_t &callSource )
{
COMET_NOTUSED(errorSource);
tostream *ofs= logger();
if (ofs==NULL) return; // Should never be NULL, as can_log_call() should have been obeyed before calling.
*ofs << _T("Err ") << callSource.source().t_str();
if ( !desc.empty() )
{
*ofs << type << _T(": ") << desc ;
}
*ofs << std::endl;
}
protected:
// Log a function call/return.
static void log_( bool return_val, const tstring &iface, const tstring &funcname, const tstring &log, const tstring &retval)
{
tostream *ofs= logger();
if (ofs==NULL) return; // Should never be NULL, as can_log_call() should have been obeyed before calling.
*ofs << (return_val?_T("Out "):_T("In ")) << iface << _T("::") << funcname;
if (!return_val || !log.empty())
*ofs << _T("(") << log << _T(")");
if (return_val && !retval.empty())
*ofs << _T(" returned ") << retval;
*ofs << std::endl;
}
// Access to the static logger instance without needing to initialise a
// member.
static tostream *logger()
{
static tostream *ofs_= NULL;
if (ofs_ ==NULL)
{
ofs_ = CREATESTREAM::create();
if (ofs_ != NULL)
{
// Safely clean up static pointer on module destruct
module().add_object_to_dispose( create_pointer_deleter( ofs_ ) );
}
}
return ofs_;
}
};
namespace impl
{
/** Redirect default logging to calllog.
* \internal
*/
template<>
struct call_logger_redirect_<true>
{
// This trick allows the user to be able to still override the call logging.
// Without this, log_exception has to call
// call_logger_<true>::log_exception which causes the template to be
// instantiated, and the user is no longer able to specialise
// call_logger_
template<bool OVERRIDE>
struct exe
{
static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource, const source_info_t &callSource )
{
call_logger_<OVERRIDE>::log_exception(type,desc,errorSource, callSource);
}
static inline bool can_log_exception()
{
return call_logger_<OVERRIDE>::can_log_exception();
}
};
};
}
#ifdef COMET_LOGFILE
#ifndef COMET_LOGFILE_DEFAULT
#define COMET_LOGFILE_DEFAULT NULL
#endif
#include <fstream>
/** \class tofstream_comet calllog.h comet/calllog.h
* Provides a filestream creator as well as the implementation of an output filestream logger.
* Allows overriding of file name.
*/
class tofstream_comet : public tofstream
{
static const char *&filename_()
{
static const char *default_filename= COMET_LOGFILE_DEFAULT;
return default_filename;
}
public:
/// Get the default filename.
static const char *get_default_filename() { return filename_(); }
/// Set the default filename to a new value.
void set_default_filename( const char *filename) { filename_() = filename; }
tofstream_comet( const char *fname) : tofstream(fname) {}
/** Create an instance of the logger.
* Returns NULL if the file doesn't exist.
*/
static tostream *create()
{
const char *fname = filename_();
if (fname == NULL)
return NULL;
return new tofstream_comet(fname);
}
private:
tofstream_comet(const tofstream_comet &);
tofstream_comet &operator=(const tofstream_comet &);
};
/** Override specialisation of the call_logger_.
* \relates call_logger_
*/
template<>
struct call_logger_<true> : public stream_call_logger_t<tofstream_comet>
{
};
#endif // FILE_LOG
/** Default interface (com_ptr) logging.
* Specialise to provide custom logging for com_ptr.
\code
template<>
void comet_log_interface<IMyInterface>(tostream &os, const com_ptr<IMyInterface> &iface)
{
os << iface->GetName();
}
\endcode
Specialisations for IUnknown and IDispatch are used by the variant loggers.
* \sa comet_log comet_log_array
* \relates call_logger_
*/
template< typename IFACE>
void comet_log_interface(tostream &os, const com_ptr<IFACE> &iface)
{
os << _T("0x") << std::hex << reinterpret_cast<unsigned long>(iface.get()) << std::dec;
}
// Forward declarations.
template<typename T> void comet_log(tostream &os, const T &value);
namespace impl
{
// Forward declarations.
template<typename T> inline void default_comet_log(tostream &os, const T &value);
static void comet_log_array_raw(tostream &os, SAFEARRAY *value);
// The default variant handler.
template< bool B>
static inline void default_comet_log_variant(tostream &os, const variant_t &value, bool out_type)
{
VARTYPE vt = value.get_vt();
if ((vt & VT_ARRAY) != 0)
{
comet_log_array_raw(os, value.get().parray);
}
else
{
VARIANT varcopy=value.in();
if (vt == (VT_BYREF | VT_VARIANT)) // Dereference variant by reference
varcopy = *V_VARIANTREF(&varcopy);
const VARIANT *var=&varcopy;
#define __VARIANT_LOGPOINTER_TYPE_CAST(vartype,cast) \
case VT_##vartype:\
if(out_type) os << _T("VT_")_T(#vartype)_T(":");\
comet_log_interface(os, cast(V_##vartype(var))); \
break
#define __VARIANT_LOGPOINTER_REFTYPE_CAST(vartype,cast) \
case VT_BYREF|VT_##vartype:\
if(out_type) os << _T("BYREF VT_")_T(#vartype)_T(":");\
comet_log_interface(os, cast(*V_##vartype##REF(var)));\
break
#define __VARIANT_LOG_TYPE_CAST(vartype,cast) \
case VT_##vartype: \
if(out_type) os << _T("VT_")_T(#vartype)_T(":"); \
comet_log(os, cast(V_##vartype(var))); \
break
#define __VARIANT_LOG_REFTYPE_CAST(vartype,cast)\
case VT_BYREF|VT_##vartype:\
if(out_type) os << _T("BYREF VT_")_T(#vartype)_T(":");\
comet_log(os, cast(*V_##vartype##REF(var)));\
break
#define __VARIANT_LOG_TYPE(vartype) \
case VT_##vartype: \
if(out_type) os << _T("VT_")_T(#vartype)_T(":");\
comet_log(os, V_##vartype(var));\
break
#define __VARIANT_LOG_REFTYPE(vartype)\
case VT_BYREF|VT_##vartype: \
if(out_type) os << _T("BYREF VT_")_T(#vartype)_T(":"); \
comet_log(os, *V_##vartype##REF(var)); \
break
switch (vt)
{
__VARIANT_LOG_TYPE(UI1);
__VARIANT_LOG_TYPE(UI2);
__VARIANT_LOG_TYPE(UINT);
__VARIANT_LOG_TYPE(UI4);
__VARIANT_LOG_TYPE(I1);
__VARIANT_LOG_TYPE(I2);
__VARIANT_LOG_TYPE(INT);
__VARIANT_LOG_TYPE(I4);
__VARIANT_LOG_TYPE(R4);
__VARIANT_LOG_TYPE(R8);
__VARIANT_LOG_REFTYPE(UI1);
__VARIANT_LOG_REFTYPE(UI2);
__VARIANT_LOG_REFTYPE(UINT);
__VARIANT_LOG_REFTYPE(UI4);
__VARIANT_LOG_REFTYPE(I1);
__VARIANT_LOG_REFTYPE(I2);
__VARIANT_LOG_REFTYPE(INT);
__VARIANT_LOG_REFTYPE(I4);
__VARIANT_LOG_REFTYPE(R4);
__VARIANT_LOG_REFTYPE(R8);
case VT_BOOL:
if(out_type) os << _T("VT_BOOL:");
os << (V_BOOL(var)==VARIANT_FALSE)?_T("true"):_T("false");
break;
case VT_BYREF|VT_BOOL:
if(out_type) os << _T("BYREF VT_BOOL:");
os << (V_BOOL(var)==VARIANT_FALSE)?_T("true"):_T("false");
break;
__VARIANT_LOG_TYPE_CAST( CY, currency_t::create_const_reference);
__VARIANT_LOG_REFTYPE_CAST( CY, currency_t::create_const_reference);
__VARIANT_LOG_TYPE_CAST( DATE, datetime_t::create_const_reference);
__VARIANT_LOG_REFTYPE_CAST( DATE, datetime_t::create_const_reference);
__VARIANT_LOG_TYPE_CAST( BSTR, bstr_t::create_const_reference);
__VARIANT_LOG_REFTYPE_CAST( BSTR, bstr_t::create_const_reference);
__VARIANT_LOGPOINTER_TYPE_CAST( UNKNOWN, com_ptr<IUnknown>::create_const_reference);
__VARIANT_LOGPOINTER_TYPE_CAST( DISPATCH, com_ptr<IDispatch>::create_const_reference);
__VARIANT_LOGPOINTER_REFTYPE_CAST( UNKNOWN, com_ptr<IUnknown>::create_const_reference);
__VARIANT_LOGPOINTER_REFTYPE_CAST( DISPATCH, com_ptr<IDispatch>::create_const_reference);
case VT_DECIMAL:
if(out_type) os << _T("BYREF VT_DECIMAL:");
os << _T("?");
break;
case VT_ERROR:
if(out_type) os << _T("VT_ERROR:");
os <<_T("0x") << std::hex << V_ERROR(var) << std::dec;
break;
case VT_BYREF|VT_ERROR:
if(out_type) os << _T("BYREF VT_ERROR:");
os <<_T("0x") << std::hex << *V_ERRORREF(var) << std::dec;
break;
default:
os << _T("???");
}
#undef __VARIANT_LOG_TYPE_CAST
#undef __VARIANT_LOG_REFTYPE_CAST
#undef __VARIANT_LOG_TYPE
#undef __VARIANT_LOG_REFTYPE
#undef __VARIANT_LOGPOINTER_TYPE_CAST
#undef __VARIANT_LOGPOINTER_REFTYPE_CAST
}
}
/* Logging for raw safearrays.
* For vector arrays of size <= 16, this fakes a variant and then uses the default variant logging to log the elements
*/
static void comet_log_array_raw(tostream &os, SAFEARRAY *value)
{
UINT dims = SafeArrayGetDim(value);
VARTYPE vt ;
if( FAILED(SafeArrayGetVartype(value, &vt ) ) )
{
os << "???";
return;
}
long ubound=-1,lbound=0; // Outside so it can be used for the '1' case below.
for (UINT d = 1; d<= dims ; ++d)
{
if( SUCCEEDED(SafeArrayGetUBound( value, d, &ubound) ) && SUCCEEDED(SafeArrayGetLBound(value, d, &lbound) ))
{
if( lbound == 0)
os << _T("[") << ubound+1 << _T("]");
else
os << _T("(") << lbound << _T("..") << ubound << _T(")");
}
}
if (dims == 1 )
{
long size = 1+ubound-lbound;
if (size ==0)
{
os << _T("{}");
}
else if( size > 0 && size <= 15)
{
// For small arrays, print out the elements.
os << _T("{");
VARIANT v;
void *var;
bool first=true, is_variant= (vt==VT_VARIANT);
if ( is_variant)
var = (void *)&v;
else
{
V_VT(&v) = vt;
var = (void *)&V_UI1(&v);
}
for (long i = lbound; i <= ubound; ++i )
{
if(first)
first = false;
else
os << _T(",");
if( SUCCEEDED( SafeArrayGetElement( value, &i, var ) ))
default_comet_log_variant<true>( os, variant_t(auto_attach(v)), first | is_variant);
}
os << _T("}");
}
}
}
// Default logging: stream the value.
template<typename T>
inline void default_comet_log(tostream &os, const T &value)
{
// ERRORS: If a compiler error occurs here, you may need to
// specialise comet_log<> to the type T here.
os << value;
}
// Default logging for bstr_t
template<>
inline void default_comet_log<bstr_t>(tostream &os, const bstr_t &value)
{
// Put quotes round the string - simplistic, don't worry about
// non-printables or escaping for the moment.
os << _T("'") << value << _T("'");
}
// Deafult logging for variants.
template<>
static inline void default_comet_log<variant_t>(tostream &os, const variant_t &value)
{
default_comet_log_variant<true>( os, value, true);
}
}
/** Type specific logger.
* The default is to use internal logging. This can be specialised to
* provide type-specific logging.
* \sa comet_log_array comet_log_interface
* \relates call_logger_
*/
template<typename T>
void comet_log(tostream &os, const T &value)
{
impl::default_comet_log(os,value);
}
namespace impl
{
// trick to work out whether it is a safearray or com_ptr type (required because of no
// partial specialisation). Needed to handle the special circumstances
template<typename T>
struct check_log_type_
{
static long check(...);
template<typename S>
static char check(const safearray_t<S> &);
template<typename S>
static short check( const com_ptr<S> &);
static T createT();
enum { is = sizeof( check( createT() ) ) };
};
template < int TYPE> struct choose_logger;
// Default safearray_t logger where we know the type T.
//
template<typename T>
inline void default_comet_log_array(tostream &os, const safearray_t<T> &value)
{
safearray_t<T>::index_type lbound=value.lower_bound(), size = value.size();
if (lbound == 0)
os << _T("[") << size << _T("]");
else
os << _T("(") << lbound << _T("..") << (lbound + size -1) << _T(")");
if( value.size() <= 15)
{
os << _T("{");
bool first = true;
for (safearray_t<T>::const_iterator it = value.begin(); it != value.end(); ++it)
{
choose_logger<check_log_type_<T>::is >::do_comet_log(os, *it);
if (first)
first=false;
else
os << _T(",");
}
os << _T("}");
}
}
}
/** Typed safearray_t logger.
* The default is to use internal logging. This can be specialised to
* provide type-specific logging.
* \sa comet_log comet_log_interface
* \relates call_logger_
*/
template<typename T>
void comet_log_array(tostream &os, const safearray_t<T> &value)
{
impl::default_comet_log_array(os,value);
}
namespace impl
{
// choose the standard logger
template < int TYPE>
struct choose_logger
{
template<typename T>
static inline void do_comet_log(tostream &os, const T &value)
{
comet_log(os,value);
}
};
// Choose the array logger
template<>
struct choose_logger<sizeof(char)>
{
template <typename T>
static inline void do_comet_log(tostream &os, const safearray_t<T> &value)
{
comet_log_array(os, value);
}
};
// Choose the interface logger
template<>
struct choose_logger<sizeof(short)>
{
template <typename T>
static inline void do_comet_log(tostream &os, const com_ptr<T> &value)
{
comet_log_interface(os, value);
}
};
// Choose which of the comet_loggers to use.
template<typename T>
static inline tostream &do_comet_log(tostream &os, const T &value)
{
choose_logger<check_log_type_<T>::is >::do_comet_log(os, value);
return os;
}
}
//@}
}
#endif /* COMET_CALLLOG_H */

View file

@ -0,0 +1,101 @@
/** \file
* Command line parser.
*/
/*
* Copyright © 2002 Mikael Lindgren
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_COMMAND_LINE_PARSER_H
#define COMET_COMMAND_LINE_PARSER_H
#include <comet/tstring.h>
namespace comet {
/*! \addtogroup Misc
*/
//@{
class cmd_line_parser
{
public:
enum kind_t {
Name, // Name type token, has no leading / or -
Option, // Option type token. Leading / or - skipped by token
Value, // Value for name or option. Leading : or = skipped by token
Done // No more tokens
};
explicit cmd_line_parser(const TCHAR* cmd_line): cmd_line_(cmd_line)
{
reset();
}
kind_t get_next_token(tstring& result)
{
static const TCHAR terminators[] = _T("=/- \t");
static const TCHAR white_space[] = _T(" \t");
kind_t kind;
token_ = next_token_ + _tcsspn(next_token_, white_space); // Skip leading whitespace
switch (*token_)
{
case 0:
return Done;
case _T('-'):
case _T('/'):
kind = Option;
++token_;
break;
case _T('='):
kind = Value;
++token_;
break;
default:
kind = Name;
break;
}
if (kind == Option || kind == Value)
token_ += _tcsspn(token_, white_space); // Skip any more whitespace
if (*token_ == _T('"'))
{
const TCHAR* next = _tcschr(token_+1, _T('"'));
if ( next )
{
result.assign( token_+1, next );
next_token_ = next+1;
return kind;
}
}
next_token_ = token_ + _tcscspn(token_, terminators);
result.assign(token_, next_token_);
return kind;
}
void reset()
{
token_ = 0;
next_token_ = cmd_line_;
}
private:
const TCHAR* cmd_line_;
const TCHAR* token_;
const TCHAR* next_token_;
};
//@}
}
#endif

View file

@ -0,0 +1,776 @@
/** \file
* Load basic comet libraries.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen, Michael Geddes
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_COMET_H
#define COMET_COMET_H
#include <comet/config.h>
/**
@mainpage Comet
See https://github.com/alamaison/comet
See \ref comethistory.
\section cometinfocontents Information Pages
<ul>
<li>\ref tlb2husage</li>
<li>\ref tlb2handidl</li>
<li>\ref cometcomptr</li>
<li>\ref cometrawcomaccess</li>
<li>\ref cometconnectionpoints</li>
<ul>
<li> \ref cometconnectionpointssource</li>
<li> \ref cometconnectionpointsink</li>
</ul>
<li>\ref comettstring</li>
<li>\ref cometdefineconfiguration</li>
<li>\ref cometcatchallexception</li>
<li>\ref cometclassfactory</li>
<li>\link custom_registration Custom Registration\endlink</li>
<li>\ref comethandleexception</li>
<li>\ref cometcalllogging</li>
<li>\ref cometautoexp</li>
<ul><li>\ref cometautoexpusage</li></ul>
</ul>
*/
/**
* \page cometrawcomaccess Raw COM Acces
* The designers of Comet have tried to avoid making the wrappers do too much
* implicitly, prefering discrete but explicit ways of triggering functionality.
*
* In order to provide interaction of Comet classes with their COM counterparts,
* a standard set of methods have been used, effectively providing a COM wrapper
* <i>concept</i>.
*
* <ul>
* <li><b>in()</b>: Return a pointer suitable for [in] parameters,</li>
* <li><b>out()</b>: Return a pointer suitable for [out] parameters, first freeing memory allocated,</li>
* <li><b>inout()</b>: Return a pointer suitable for [in,out] parameters.</li>
* <li><b>detach()</b>: Detach and return the internal pointer from the object</li>
* <li><b>in_ptr()</b>: {optional} Return a pointer suitable for [out] parameter where a pointer is required, first freeing memory allocated</li>
* <li><b>get()</b>: {optional} Returns a pointer to the internal pointer (same as STL pointers)</li>
* <li><b>auto_attach( RAW_TYPE )</b>: Cause an assignment to attach the object to the specified raw COM type.</li>
* <li><b>create_reference( RAW_TYPE )</b>: Static method to create a propper wrapper reference to the specified raw object.</li>
* <li><b>create_const_reference( RAW_TYPE )</b>: Static method to create a const wrapper reference to the specified raw object.</li>
* </ul>
*/
/** \page cometcatchallexception Exception Catching Policy
In an ideal world, Microsoft would have adhered to the C++ standard, and made
<kbd>catch(...)</kbd> not catch system exceptions like 'Access Violation',
however this is not the case.
To make it worse, not only do system exceptions get caught by <kbd>catch(...)</kbd>,
they also <b>bypass the stack unwinding</b>. This is quite problematic in an
environment where this mechanism is relied upon for resource management, commonly
'only' memory, but also including multithreading acces control mechanisms.
One of the big problems with Access Violations is that it is an unplanned
exception, and in many situations will leave data structures incomplete,
resources locked or other equally vicious artifacts. Essentially, it breaks
invariants. One viable take on this is that if you don't know where an
exception came from, you shouldn't be catching it.
A big advantage of letting access violations and it's ilk (or any other
unplanned exception) through is that these will then get caught by the JIT (Just
In Time) handlers such as Dr. Watson and Compiler environments that allow
immediate or post-mortem debugging of the problem. A lot of projects (like
Mozilla) have their own bug-reporting which can intercept the bugs at the top
level and generate their own crash dumps, and catching these exceptions is
actually going to bypass a very useful mechanism.
All this is to say that we have made a shift away from exception handling
policies that cause system expeptions to be caught, however in order to
allow as much flexibility as possible, an improved exception handling mechanism
has been added to the interface implementations and to the server implementation
that uses catch and rethrow to allow logging and custom handling of all exceptions.
The default action of the mechanisms will be to finally rethrow unknown
exceptions. The good thing about this is that the rethrow behaves to a JIT handler
as if the expeption had never been caught.
*/
/** \page cometautoexp Comet AutoExp.Dat Support
There is a largely undocumented feature is Visual Studio 6 and 7 that allows
you to create a dll 'ADDIN' that provides custom formatting for variables in the
debugger. CometAutoExp.dll allows you to view simple automation types in more
detail than currently provided internally by the debugger.
By enabling this, you will get to see real date/times when you view datetime_t, you
get to see SAFEARRAY types (including IIDs), and possibly their contents, you
will see full VARIANT types, including SAFEARRAYs.
The file in comet/src/cometautoexp/AutoExp.dat shows the entries that will
be needed to included in your own AutoExp.dat for this to work. (Usually
found at "c:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin\AUTOEXP.DAT")
See \ref cometautoexpusage for more information on how to use this.
*/
/** \page cometdefineconfiguration Comet Configuation
While Comet barely uses macros for the import work of creating a COM library,
there are a number of preprocessor switches that are used to alter certain
behaviours and select code. While most of these refer to the compiler being used,
there are a few that are intended to be used as external switches.
<ul><li><b>COMET_ALLOW_DECLSPEC_PROPERTY</b> : Wrapper headers include declspec
properties, allowing interface properties to be assigned-to and read as
properties.</li> <li><b>COMET_ASSERT_THROWS</b> : Comet throws
comet::assert_failed when internal assertions fail in debug builds.</li>
<li><b>COMET_ASSERT_THROWS_ALWAYS</b> : Comet throws comet::assert_failed when
internal assertions fail in both debug and release builds.</li>
<li><b>COMET_LOGFILE</b> : See \ref cometcalllogging.</li>
<li><b>COMET_LOGFILE_DEFAULT</b> : See \ref cometcalllogging. </li>
<li><b>COMET_NO_MBCS</b> : Disable comet multi-byte-character-set conversion handling.</li>
<li><b>COMET_NO_MBCS_WARNING</b> : Turn off the warning indicating that sdt::string is not compatible with MBCS.</li>
<li><b>COMET_USE_RAW_WRAPPERS</b> : Tells com_ptr not to use the comet wrappers but to return raw interface pointers. </li>
</ul>
There are also a number of macros that are either utitlity macros, reflect compiler differences
or Comet version differences that may be convenient to use within your own code.
<ul>
<li><b>COMET_ASSERT(expression)</b> : Run-time assert.</li>
<li><b>COMET_STATIC_ASSERT(static-expression)</b> : Compile-time assert.</li>
<li><b>COMET_NOTUSED(info)</b> : Specify unused argument.</li>
<li><b>COMET_FORCEINLINE </b> : Use before a method to apply force-inline if available. </li>
<li><b>COMET_VARIANT_TRUE,COMET_VARIANT_FALSE</b> : Use in place of VARIANT_TRUE,VARIANT_FALSE to avoid type warnings.</li>
<li><b>COMET_MAJOR_VER </b> : Major comet version</li>
<li><b>COMET_MINOR_VER </b> : Minor comet version</li>
<li><b>COMET_BUILD </b> : Comet version to compare against (yyyymmdd of distribution)</li>
<li><b>COMET_STRICT_TYPENAME </b> : Used for when stricter compilers require 'typename' keyword and VC6 has an error.</li>
<li><b>COMET_CONST_TYPE(vartype, varname, value)</b> : Define a typed constant for a class/struct (or use enum if not supported) </li>
</ul>
*/
/** \page comethistory Comet History
\par Version 1 gamma 32 ( )
\li Support for VC++2005 (Sofus Mortensen)
\li Numerous bug fixes and better support for Intel C++ (Richard Crossley)
\li Fixed off-by-one bug regarding array sizes (Yunusov Bulat)
\par Version 1 beta 31 ( )
\li safearray.h - Fix a few omissions/bugs (Lijun Qin)
\li comet_lint.lnt - Add pclint options file. (Michael Geddes)
\li server.h - Fix singlton_autorelease class (Ralf Jürgensen)
\li datetime.h - Fix bug in century non-leap-years. (Michael Geddes)
\li datetime.h - Use julian date conversions from boost - to drastically improve split/join efficiency (Michael Geddes)
\li datetime.h - Make invalid() rather than valid() the default (Michael Geddes)
\li date.h - Make use of above improvements in datetime_t (Michael Geddes)
\li datetime.h/date.h - Add ability to construct/assign invalid/null dates from dt_null, dt_invalid (Michael Geddes)
\li datetime.h - Fixed bug in to_unixtime (Lijun Qin)
\li array.h - Fixed typename problem (Sofus Mortensen)
\li safearray.h - Fixed problem with sa_debug_iterator and MSVC 7.1 (Sofus Mortensen)
\li uuid_fwd.h - Fixed bug in !operator (Sofus Mortensen)
\par Version 1 beta 30 (2004-3-5)
\li Support for VC7.1 partial specialisation. (Lijun Qin)
\li datetime.h - Bugfix in datetime_t conversion (Gordon Donaldson)
\li safearray.h - Separate safearray_t::resize into resize and resize_bound to avoid ambiguous conversions. (Michael Geddes)
\li safearray.h - Fix bug in safearray_t:resize_bound using an incorrect copy. (Michael Geddes)
\li safearray.h - Add safearray_t debug iterator for debug builds. (Michael Geddes)
\li safearray.h - Add more comments for safearray_t (Michael Geddes)
\li safearray.h - Support more container-type methods (erase,push_front,push_back,pop_front,pop_back) (Michael Geddes)
\li server.h - Add auto-release singleton (Michael Geddes)
\li uuid.h - uuid_t::operator! no longer reversed (Lijun Qin)
\li uuid.h - fix ambiguous ++ operator usage. (Lijun Qin, Bulat Raditch, Michael Geddes)
\li handle.h - Extension of handles for GDI objects for cometw (Michael Geddes/Vladimir Voinkov/Lindgren Mikael)
\li bstr.h - Throw comparison errors if they occur. (Michael Geddes)
\li cp.h - add 'is_connected' method to connection points. (Lijun Qin)
\li common.h - Support for pclint (Michael Geddes, Gabriel Barta)
\li datetime.h - Support for timezones (Michael Geddes)
\li datetime.h - Fix up buffer handling (Michael Geddes, Lijun Qin)
\li variant.h - Support for strings with embedded nulls (Michael Geddes)
\li tlb2h - Support for bool in structs and in safearrays (Michael Geddes)
\li tlb2h - Support for wrapper renaming of specific methods on specific interfaces/struct/unions. (Michael Geddes)
\li tlb2h - Dual interfaces inherited from an interface in a different type-library now works when called by dispatch (Michael Geddes)
\li tlb2h - Output of HTML now better restricted to only required interfaces. (Michael Geddes)
\li tlb2h - Obey COM rules that require [out] pointers to be initialised on failure (Michael Geddes)
\li tlb2h - Support implementation of an interface that inherits from an interface from a different typelibrary (Michael Geddes)
\li cometautoexp - Support for more types, and better handling of strings. (std::basic_string, COLEDateTime) (Michael Geddes)
\li date.h - Added dateonly_t class. (Michael Geddes)
\li uuid.h - Make the strings accessors consistant (Michael Geddes, Lijun Qin)
\par Version 1 beta 29 (2003-12-30)
\li Added loads of documentation, reduced doxygen warnings to 1(Michael Geddes)
\li Added CometAutoExp.dll extended support for AutoExp.dat
\li Remove unnecessary catch(...) - use specific catches (Michael Geddes)
\li Support create_const_reference in all wrapper classes. (Michael Geddes)
\li tlb2h - Enhance support for error information (interface/coclass name) (Michael Geddes)
\li tlb2h - Add support for logging calls &amp; exceptions. (Michael Geddes)
\li tlb2h - Support for special characters in help strings. (Michael Geddes)
\li tlb2h - Few tweaks to get correct output. (Michael Geddes)
\li tlb2h - Option to show version (Michael Geddes)
\li bstr.h - Work with _STLP_DEBUG wrappers (Michael Geddes)
\li bstr.h - Constructor works with MBCS (Michael Geddes)
\li bstr.h - Support for {} round uuid_t (Michael Geddes)
\li cp.h - Add convenience methods. (Michael Geddes)
\li datetime.h - Constructor to supply date and time (Michael Geddes)
\li datetime.h - Support output streams. (Michael Geddes)
\li error.h - Support for source, iid and helpfile in errors. (Michael Geddes)
\li interface.h - Provide extra comtype definitions. (Michael Geddes)
\li interface.h - Provide convenience macro to define extra comtype with IID_ instances. (Michael Geddes)
\li ptr.h - Add identity_ptr class that references an identity IUnknown. All other comparisons QI on <b>both</b> pointers. (Michael Geddes)
\li server.h - Add support for singelton classes. (Michael Geddes)
\li tlbinfo.h - Fix up reference counting on struct wrappers. (Michael Geddes)
\li tlbinfo.h - Support ITypeInfo2 (Michael Geddes)
\li variant.h - Added explicit converts (as_uchar(), as_uint(), as_double() etc) (Michael Geddes)
\li variant.h - Added is_empty(), is_null() and is_nothing() (Michael Geddes)
\par Version 1 beta 28 (2003-6-18)
\li Support for Visual Studio 2003
\par Version 1 beta 27 (2003-3-5)
\li tlb2h - bug fix variant_t members of dispinterfaces (Michael Geddes)
\li tlb2h - support for safearrays of interfaces (Michael Geddes)
\par Version 1 beta 26 (2003-2-1)
\li tlb2h - major update. See http://groups.yahoo.com/group/tlb2h/message/706 (Michael Geddes)
\li Enum.h - allow copy policies with members (Michael Geddes)
\li datetime.h - fixed bug in timeperiod_t::split (Michael Geddes)
\par Version 1 beta 25 (2002-11-28)
\li Connection point implementation is now customisable via traits. See http://groups.yahoo.com/group/tlb2h/message/688 (Michael Geddes)
\li Fixed bug in str_formattime in datetime.h (Sofus Mortensen).
\li Fixed bug in add_months in datetime.h (Michael Geddes).
\par Version 1 beta 24 (2002-11-13)
\li Major update of tlb2h. See http://groups.yahoo.com/group/tlb2h/message/659 and http://groups.yahoo.com/group/tlb2h/message/661. (Michael Geddes)
\li Fixed problem with variant_t::operator==. (Kyle Alons)
\li Fixed bug in bstr_t::s_str(), bstr_t::is_empty(), bstr_t::length() (Mikael Lindgren, Michael Geddes)
\li safearray_t: 1. Changed the constructor that takes two iterators to not have a default lowerbound (to be consistant with the other constructor)
2. Changed resize to allow specifying a lower-bound.
3. Changed the default lb to be 0 in the case where none is specified and where the safearray is NULL. (Michael Geddes)
\par Version 1 beta 23 (2002-9-1)
\li Bug fixes to namespace handling. (Michael Geddes)
\li Added friendly error message for missing tlbinf32.dll. (Sofus Mortensen)
\li Worked around MSVC6 internal compiler error when contructing an enum. (Michael Geddes)
\li Bug fixes to currency.h (Michael Geddes)
\li Bug fixes to datetime.h (Michael Geddes)
\par Version 1 beta 22 (2002-8-19)
\li Update of tlb2h - better handling of namespace mangling, and support for
unwrapping the type of aliases without unwrapping the name of the aliases (Michael Geddes).
\li Fixed bug in uuid_fwd. (John Harrison)
\li Added oleidl_comtypes.h. (Gabriel Barta)
\li Restored old functionality of try_cast - will no longer throw when casting a null pointer. (Sofus Mortensen)
\li New auto-locking implementation of safearray_t::create_reference and safearray_t::create_const_reference. (Michael Geddes, Sofus Mortensen)
\li Included first drop (pre-alpha version) of cometw. (Vladimir Voinkov)
\par Version 1 beta 21 (2002-6-21)
\li Fixed null pointer bug in com_error::what(). (Kyle Alons)
\li Fixed bug to do with the unloading of typelibraries when refcount reaches zero. (Michael Geddes)
\li Added support for MBCS to std::string and const char* conversions for bstr_t. Only active when _MBCS is defined. (Michael Geddes)
\li Fixed locking/unlocking bug. (Vladimir Voinkov, Sofus Mortensen)
\li Fixed bug in safearray_t::create_reference(variant_t&). (Michael Geddes)
\li Various fixes to datetime and currency. (Michael Geddes)
\li Added constants COMET_VARIANT_TRUE and COMET_VARIANT_FALSE in order to avoid warnings. (Michael Geddes, Sofus Mortensen)
\li registry::value has been extended with overload for method str and dword, where a default value can be supplied if the key/value does not exist. (Sofus Mortensen)
\li Various patches for BCC. (Michael Geddes)
\li Solved problem with vtables gaps when inheriting from those interfaces. (Michael Geddes)
\li Removed a few level 4 warnings. (Michael Geddes)
\li Added experimental HTML generation to tlb2h. (Sofus Mortensen)
\par Version 1 beta 20 (2002-4-9)
\li tlb2h will fall back to using raw structs for structs with types that cannot be wrapped. (Sofus Mortensen)
\li Added application wizard for MSVC.NET. See tlb2h/src/Comet. (Sofus Mortensen)
\li Eliminated a few warnings. (Sofus Mortensen)
\par Version 1 beta 19 (2002-3-26)
\li Added caching of IRecordInfo to sa_traits for wrapped structs and ITypeInfo to IDispatch implementations. (Sofus Mortensen)
\li Fixed problem with safearray_t iterators on MSVC7. (Sofus Mortensen)
\li Fixed bug regarding range checking for safearray_t::at being off by one. (Sofus Mortensen)
\li Added range checking assertion (debug only) to safearray_t::operator[]. (Sofus Mortensen)
\li Changed safearray_t constructor, so that lower bound of one is no longer assumed. Instead lower bound must be specified. (Sofus Mortensen)
\par Version 1 beta 18 (2002-3-25)
\li Major revision of bstr_t. (Sofus Mortensen)
\li Added experimental support for wrapped structs to tlb2h and safearray. (Sofus Mortensen)
\li Fixed problem with having a coclass as a connection point sink. (Sofus Mortensen)
\li Revised treatment of [in, out] parameters in tlb2h. The old implementation could cause double deletion of [in. out] parameters when an exception was thrown. (Sofus Mortensen)
\li Revised all wrapper classes, in order for create_reference to create a mutable reference and create_const_reference an immutable reference. (Sofus Mortensen)
\li Revised locking in safearray_t. safearray_t::create_reference and safearray_t::create_const_reference is no longer doing automatic locking. (Sofus Mortensen)
\li tlb2h now generates #import alike smart pointer typedef. Ie. interface IFoo will be matched with a typedef com_ptr<IFoo> IFooPtr. (Sofus Mortensen)
\li Added support for datetime_t and currency_t to safearray_t. (Sofus Mortensen)
\li Added t_str() to bstr_t for converting to tstring. (Sofus Mortensen)
\par Version 1 beta 17 (2002-2-18)
\li Fixed bug in atl_module. (Michael Geddes)
\li Documentation update for bstr.h. (Michael Geddes)
\li bstr_t now supports strings with embedded nulls. Thanks to Eric Friedman for reporting this. (Sofus Mortensen)
\li Removed use of _alloca in bstr.h. (Sofus Mortensen)
\par Version 1 beta 16 (2002-2-12)
\li Fixed bug in functors bstr::less, bstr::less_equal, bstr::greater, bstr::greater_equal, bstr::equal_to and bstr::not_equal_to. (Michael Geddes)
\li tlb2h: switched ResolveAliases off per request from Michael Geddes.
\li tlb2h: Removed dummy wrapper methods (see http://groups.yahoo.com/group/tlb2h/message/476). (Sofus Mortensen)
\par Version 1 beta 15 (2002-2-1)
\li Added lw_lock class based on Brad Wilson's LightweightLock (see http://www.quality.nu/dotnetguy/archive/fog0000000007.aspx). Many thanks to Brad for making LightweightLock open source. (Sofus Mortensen)
\li Comet now works with MSVC7. (Sofus Mortensen)
\li Removed functor.h. (Sofus Mortensen)
\li Fixed serious bug in bstr_base - causing memory corruption when concat'ing bstr's. (Michael Geddes)
\li Fixed obvious typo in locking_ptr. (Vladimir Voinkov)
\li Removed unnecessary include dependency from scope_guard.h. (Vladimir Voinkov)
\li Fixed compatibility problem with STLport for bstr comparison functors. (Michael Geddes)
\li Removed level 4 warnings from currency.h. (Michael Geddes).
\li Fixed problem with the -c option in tlb2h. (Michael Geddes).
\li Fixed bug in ATL_module.h. (Michael Geddes)
\li impl_dispatch is now lazy loading TypeInfo. Better performance for dual interfaces where client is not using IDispatch. (Sofus Mortensen)
\li Fixed various bugs in tlb2h. (Sofus Mortensen)
\par Version 1 beta 14 (2002-1-17)
\li Fixed problem with dispinterfaces and [in, out] enum parameters. (Sofus Mortensen)
\li Added simple system to prevent compiling out-of-date tlb2h generated headers. (Sofus Mortensen)
\li Fixed bug in impl_dispatch. (Michael Geddes, Sofus Mortensen)
\par Version 1 beta 13 take 4 (2002-1-11)
\li Fixed problem with dispinterfaces and enum parameters reported by Kyle Alons. (Sofus Mortensen)
\li Fixed serious bug in iterators for safearray_t reported by Steve Broeffle. The bug was caused by a MSVC compiler bug. (Sofus Mortensen)
\li Fixed bug operator in operator[] in iterators for safearray_t. (Sofus Mortensen)
\par Version 1 beta 13 take 3 (2002-1-9)
\li Fixed bug in uuid_t introduced in beta 13 take 2. (Sofus Mortensen)
\par Version 1 beta 13 take 2 (2002-1-7)
\li Beta 13 couldn't compile with _UNICODE defined. Fixed now. (Sofus Mortensen)
\par Version 1 beta 13 (2002-1-7)
\li Added basic support for writing exe servers in Comet. (Mikael Lindgren, Sofus Mortensen)
\li Added simple command line parser class to new header comet/cmd_line_parser.h (Mikael Lindgren)
\li Added new header comet/tstring.h. Defines tstring, tistream, tostream, etc, etc. (Sofus Mortensen)
\li Fixed various bugs in uuid_t. (Sofus Mortensen)
\par Version 1 beta 12 (2001-12-20)
\li Revision of embedded_object. embedded_object now takes parent type as first argument, arguments 2, 3, 4, .. denotes interfaces to implement.
embedded_object_1 has been removed. embedded_object2 has been added, extends embedded_object with functionality to
disconnect a child object from its parent. (Sofus Mortensen with help from Kyle Alons).
\li Added new file dispatch.h with specialisation of wrap_t<IDispatch> with similar (but superior) functionality as CComDispatchDriver.
\li Added new class dynamic_dispatch to dispatch.h. Use dynamic_dispatch to dynamically implement IDispatch - adding methods and properties at runtime. (Sofus Mortensen)
\li Changed interface of sink_impl so that unadvise no longer takes an argument. Additionally the destructor will unadvise if necessary. (Sofus Mortensen)
\li Added new file uuid.h with GUID/UUID/CLSID wrapper called uuid_t. (Sofus Mortensen)
\li Changed tlb2h to support new wrapper uuid_t. (Sofus Mortensen)
\li Fixed potential thread safety problem regarding class factories. (Sofus Mortensen, Paul Hollingsworth)
\par Version 1 beta 11 (2001-11-16)
\li Major fix to tlb2h. tlb2h now supports properties in dispinterfaces. (Sofus Mortensen)
\li Module constants are now static. (Sofus Mortensen)
\li tlb2h now skips non-COM interfaces that do not derive (directly or transitively) from IUnknown. (Sofus Mortensen)
\li Fixed problem with error messages ending up as garbage in tlb2h. (Kyle Alons)
\li Various fixes regarding safearray_t. (Michael Geddes and Sofus Mortensen)
\li Various other minor fixes. (Sofus Mortensen)
\par Version 1 beta 10 (2001-10-17)
\li class coclass changed so that the 3, 4, ... template parameters specifify additional interfaces to implement.
Example:
\code
template<> coclass_implementation<Foo> : public coclass<Foo, thread_model::Both, IBar>
\endcode
(Sofus Mortensen)
\li Aggregating another component is now done by adding class aggregates to the type list of interfaces. First template argument of class aggregates is the coclass
to aggregating. The 2, 4, ... template arguments specify which interfaces to aggregate. If no interfaces have been specified, all interfaces will be aggregated.
Example:
\code
template<> coclass_implementation<Foo> : public coclass<Foo, thread_model::Both, aggregates<Bar, IBar> >
\endcode
(Sofus Mortensen)
\li Added cmp method to bstr_base which a.o.t. can be configured for case insensitive comparision. (Michael Geddes)
\li Added comparison functors based on cmp to bstr_base, less, less_equal, equal_to, etc. Example of usage:
\code
std::set<bstr_t, bstr_t::less<cf_ignore_case> > mySet;
\endcode
(Sofus Mortensen)
\li Fixed bugs in assignment operators for datetime_t. (Sofus Mortensen, Mikael Lindgren)
\li In ptr.h changed COMET_ALLOW_DECLSPEC_PROPERTY to COMET_USE_RAW_WRAPPERS. (Michael Geddes)
\li In common.h added workaround for VARIANT_TRUE resulting in a level 4 warning. (Michael Geddes)
\li Changed server.h, so that a compiler error will occur if there are unimplemented coclasses. In case you deliberately want
unimplemented coclass define COMET_ALLOW_UNIMPLEMENTED_COCLASSES in std.h. (Sofus Mortensen)
\li Added various helper functions to util.h. (Sofus Mortensen)
\li Added support for aggregating the free threaded marshaler. Example:
\code
template<> coclass_implementation<Foo> : public coclass<Foo, thread_model::Both, FTM>
\endcode
(Sofus Mortensen)
\li Various bug fixes and changes. (Sofus Mortensen)
\par Version 1 beta 9 (2001-9-23)
\li Now wrapper properties and methods are only available through com_ptr::operator->. (Sofus Mortensen)
\li Added ostream<> outputting facility to both variant_t and bstr_t. (Sofus Mortensen)
\li Added std::string conversions to variant_t. (Sofus Mortensen)
\li Fixed various bugs in tlb2h regarding dispinterfaces. (Sofus Mortensen).
\li Fixed bug in com_ptr - try_cast'ing from variant_t to com_ptr did not throw an exception on error. (Sofus Mortensen)
\li Made com_ptr constructor from variant_t and assignment from variant_t private in com_ptr to prevent misuse. Use com_cast or try_cast. (Sofus Mortensen)
\par Version 1 beta 8 (2001-9-19)
\li Fixed bugs in tlb2h regarding datetime_t. (Sofus Mortensen)
\li Wrapper properties are now only available when accessing an interface through com_ptr::operator->. (Sofus Mortensen)
\li Classes currency_t and datetime_t are now exception safe. (Sofus Mortensen)
\li Added conversions for variant_t from/to currency_t and datetime_t. (Sofus Mortensen)
\li Added conversions for std::wstring to variant_t, solving various ambiguity problems. (Sofus Mortensen)
\li Re-arranged various header files, solving include problems. (Sofus Mortensen)
\par Version 1 beta 7 (2001-9-7)
\li Added support for locking to safearray_t. (Michael Geddes)
\li Improved support in tlb2h for methods taking arrays as argument. (Sofus Mortensen)
\li Fixed bug in tlb2h regarding methods that were the parameters were wrongly given a default value. (Sofus Mortensen)
\li Fixed bug in tlb2h regarding type "void *". (Sofus Mortensen)
\li Fixed various bugs in datetime.h. (Michael Geddes)
\li Added COMET_ASSERT - a replacement for _ASSERTE. (Sofus Mortensen)
\par Version 1 beta 6 take 2 (2001-8-20)
\li Fixed dumb, dumb _ASSERTE bug in tlb2h (Sofus Mortensen).
\par Version 1 beta 6 (2001-8-19)
\li Changed distribution package - now including scripts for generating docs and the source for both tlb2h and the Comet App. wizard (Sofus Mortensen).
\li Wrapped string constant in server.h with _T( ) for UNICODE compatibility (Sofus Mortensen).
\li Tlb2h.exe now generates vtable fillers to cater for interfaces with gaps in the vtable. Such are typically produced by VB (Michael Geddes and Sofus Mortensen).
\li Bug fixes to date_t (Michael Geddes).
\li Elimination of compiler warnings in safearray_t and registry.h (Michael Geddes).
\par Version 1 beta 5 (2001-8-14)
\li tlb2h.exe now generates corrects defaults for [optional] VARIANT. variant_t has been updated in order to support this (Sofus Mortensen).
\li Fixed problem in tlb2h.exe with using COMET_ALLOW_DECLSPEC_PROPERTY when importing msado20.tlb (Sofus Mortensen).
\li Fixed problem in tlb2h.exe with aliases being treated as records (Michael Geddes).
\li Several bug fixes to nutshell generation (Michael Geddes).
\li Changed tlb2h, so that the generated headers only #include the headers needed (Michael Geddes).
\par Version 1 beta 4 (2001-7-25)
\li datetime_t has been updated and support for datetime_t has been added to tlb2h.exe (Michael Geddes).
\li typelist::index_of bug fix (Michael Geddes, Sofus Mortensen, thanks to Eric Friedman for reporting this).
\li typelist::type_at bug fix (Michael Geddes).
\li create_reference added to safearray_t (Michael Geddes).
\li Experimental attach_from / attach_to added to safearray_t (Michael Geddes).
\li Bug fix in variant.h (Sofus Mortensen).
\par Version 1 beta 3 (2001-7-14)
\li MSVC7 beta 2 compatibility fixes (Sofus Mortensen).
\li Various bug fixes in tlb2h (Sofus Mortensen).
\li Added wizard option to tlb2h for generating skeleton implementation of coclasses (Michael Geddes).
\li Various bug fixes to safearray.h (Michael Geddes).
\li variant_t now supports converion to/from saferray_t (Michael Geddes, Sofus Mortensen)
\li com_ptr can now be used to wrap a pointer to coclass_implementation (Michael Geddes).
\li enum.h and cp.h has been updated to support the changes to com_ptr (Michael Geddes).
\li Preliminary version of datetime_t has been added (Michael Geddes).
\par Version 1 beta 2 (2001-7-04)
\li Major documentation update (Michael Geddes).
\li Bug fix in tlb2h.cpp (Michael Geddes).
\li Replaced operator bool in com_ptr with a more bullet proof alternative (Sofus Mortensen).
\li Updated functor.h to make use of partial specialisation for compilers that support it (Michael Geddes).
\par Version 1 beta 1 (2001-6-29)
\li Added currency support to variant_t (Michael Geddes).
\li Documentation update for server.h (Michael Geddes).
\li Various bug fixes to do with agg-objects (Michael Geddes).
\li Added GetClassObject implementation to atl_module (Michael Geddes).
\par Version 1 alpha 10 (2001-6-26):
\li CURRENCY wrapper updated by Michael Geddes.
\li tlb2h has been updated by Michael Geddes (again!). This time with options to specify which namespace to put wrappers in, and an options to emit symbols only for faster compilation.
\li atl_module.h documentation updated by Michael Geddes.
\par Version 1 alpha 9 (2001-6-21):
\li CURRENCY wrapper added by Michael Geddes.
\li Nutshell wrappers didn't work in alpha 8. Now fixed.
\li tlb2h has been updated by Michael Geddes for better command line handling. It now supports multiple files including wildcards, and support for specifying an output directory.
\li Server implementation updated by Michael Geddes to support loading type libraries that has not yet been registered.
\li try_cast no longer throws on null pointers, and comet::com_ptr::operator->() now throws on null pointers. (Michael Geddes)
\par Version 1 alpha 8 (2001-6-10):
\li Compatibility patches for GCC/MINGW submitted by Michael Geddes.
\li Updated com_error with methods for accessing wrapped HRESULT value and IErrorInfo (source, helpfile, etc).
\li Various minor bug fixes.
\par Version 1 alpha 7 take 3 (2001-3-31):
\li Added converters for CURRENCY to variant_t..
\li Updated functor.h.
\par Version 1 alpha 7 take 2 (2001-3-28):
\li Fixed bug concerning using com_cast and try_cast with raw interface pointers.
\li Fixed bug in bstr.h
\li Fixed dependency on comet/stl.h in comet/enum.h
\par Version 1 alpha 7 take 1 (2001-3-26):
\li Support for dispinterfaces has been added by Michael Geddes and Mikael Lindgren.
\li BCC compatibility patches contributed by Michael Geddes.
\li Support for multiple connection points added by Michael Geddes.
\li Added generalised functor library that works with MSVC (Not really COM related)
\li comet::make_list\<\> has changed behaviour. Instead of writing make_list\<IFoo, IBar\>, you have to write \link comet::make_list make_list\<IFoo,IBar\>::result \endlink. This has been done in order to shorten error messages relating typelists.
\li Added several helper classes to comet/typelist.h for manipulation of typelists.
\li Fixed various "ambiguous conversion" errors
\par Version 1 alpha 6 (2001-3-7):
\li Fixed disastrous bug in comet::com_ptr.
\li Re-organisation of header files.
\li Support for Intel C++ 5.0 added.
\li Fixed bug in regkey.
\li Various bugs fixes.
\par Version 1 alpha 5 take 2 (2001-1-26):
\li Fixed bug in ptr.h
\par Version 1 alpha 5 (2001-1-16):
\li Support for implementing aggregateable components. (Michael Geddes)
\li comet::com_ptr is no longer using common base class.
\li Various bug fixes.
\par Version 1 alpha 4.2 (2000-12-17):
\li Fixed bug in critical_section.
\par Version 1 alpha 4.1 (2000-12-14):
\li Fixed bug in variant.h
\li Added support for DATE and CURRENCY to tlb2h. (We might need wrapper classes for those).
\li Fixed missing inline in common.h.
\par Version 1 alpha 4 (2000-12-12):
\li Generated wrappers, interfaces, etc are now placed in namespace corresponding to typelibrary name by tlb2h.
\li Fixed bugs in variant.h
\li The generated wrappers are no longer using .get_raw() and .get_raw_ptr(). Instead the wrapper methods .in(), .in_ptr(), .inout() and .out() are being used.
\li Support for constants placed in type library modules. (See Joav Kohn's posting on ATL discuss).
\li Support for version numbering for ProgID's. (Thanks to Mikael Lindgren).
\li Updated the wizard.
\par Version 1 alpha 3 (2000-11-29):
\li Added sanity checking to safearray_t to capture type mismatches.
\li Added in() method to all wrapper classes for use when calling raw interfaces.
\li The generated header files are now using a normal include guard instead of #pragma once.
\li Various minor fixes.
\par Version 1 alpha 2 (2000-11-20):
\li Nutshell generation added to tlb2h.exe.
\li Added STL compatible SAFEARRAY wrapper called comet::safearray_t<T>.
\li Updated registry class.
\li New BSTR wrapper, comet::bstr<boolean> with optional reference counting.
\li comet::bstr_t is now a typedef of comet::bstr<false>.
\li ATL support added.
\par Version 1 alpha 1 (2000-10-29):
\li First alpha release of Comet.
\par Version 0.9.7 (2000-10-19):
\li typedef bug fix in tlb2h.exe
\li Bug fixes in comet::variant_t
\par Version 0.9.6 (2000-10-19):
\li Documentation updates.
\li Misc. bug fixes.
\par Version 0.9.5 (2000-10-5):
\li Documentation updates.
\li Paul Hollingsworth has been busy minimising include dependencies in the header files.
\li Added [out] and [in, out] adapters for dealing with raw interfaces.
\par Version 0.9.4 (2000-10-4):
\li Fixed more bugs in comet::com_ptr.
\li Added documentation on comet::com_ptr.
\par Version 0.9.3 (2000-9-26):
\li Fixed various bugs in comet::com_ptr.
\par Version 0.9.2 (2000-9-25):
\li Updated tlb2h to use const where appropiate.
\li Added support for unions.
\li Added support for one-dimensional arrays in structs.
\par Version 0.9.1 (2000-9-21):
\li Experimental support in tlb2h.exe for optional method arguments (ie. attribue optional or defaultvalue).
\par Version 0.9.0 (2000-9-19):
\li Paul Hollingsworth has contributed automatic implementation of IProvideClassInfo.
\li Better support for [in, out] parameters.
\li Fixed bugs in tlb2h's generation of connection point wrapper.
\li Removed progid from template parameters, instead override function get_progid().
\li Added version metadata to coclass and typelibrary wrappers.
\li Fixed bug in variant_t::variant_t(const comet::bstr_t&).
\par Version 0.8.3 (2000-9-12):
\li Removed DLL dependency for tlb2h.exe.
\par Version 0.8.2 (2000-9-7):
\li com_error / raise_exception_t has been revised.
\li Fixed bug in com_ptr::operator=(int)
\li Rearranged header inclusion introducing error_fwd.h.
\li Added misc. utility classes not necessarily related to tlb2h to tlb2h/utility.h.
\li Updated tlb2h.exe with more types.
\par Version 0.8.1 (2000-9-3):
\li Type conversions to/from bstr_t has been changed/tweaked.
\li bstr_t now supports concatenation through operator+ and operator+=.
\par Version 0.8.0 (2000-8-31):
\li Fixed several bugs in tlb2h.exe.
\li Added misc. utility classes not necessarily related to tlb2h to tlb2h/utility.h.
\par Version 0.7.10 (2000-8-25):
\li Updated AppWizard to generate uuid for type library.
\li Added trait class to com_server for servers with no embedded type library.
\par Version 0.7.9 (2000-8-21):
\li bstr_t is now capable of converting to std::string as well.
\li Rearranged util.h into list.h, common.h and util.h.
\par Version 0.7.8 (2000-8-18):
\li Added simple AppWizard for creating DLL projects.
\li Removed untie. Instead embedded_object now has a release_from_owner method.
\li structs defined in type libraries now automatically use CoTaskMem when using new/delete.
\par Version 0.7.7 (2000-8-15):
\li Changes to lifetime of embedded_object. Introducing tlb2h::untie, breaks tie between owner and embedded_object, so that the embedded_object can be destroyed before the owner.
\par Version 0.7.6 (2000-8-15):
\li Various changes to comet::bstr_t.
\par Version 0.7.5 (2000-8-13):
\li Interface inheritance problems solved.
\li Problem with [in] VARIANT arguments solved.
\li create_enum now works with embedded_objects.
\li comet::make_list now handles up to 40 elements.
\li Problem with IUnknown interfaces in coclasses solved.
\li Workaround for bug in Visual Studio editor causing VS to crash when editing certain template code.
\par Version 0.7.4 (2000-8-8):
\li Conversion from comet::com_ptr to comet::variant_t improved.
\li Updated example to demonstrate now working COM enumeration implementation on STL containers.
\par Version 0.7.3 (2000-8-8):
\li Nasty connection point bug fixed.
\li Added trivial VB client example program demonstrating connection point.
\li Added com_cast and try_cast for casting interface pointers. Implicit casting no longer allowed.
\li comet::com_error::what() is now working.
\li Misc. minor bug fixes/tweaks.
\par Version 0.7.2 (2000-8-3):
\li Updated the example with registration custom build.
\li Misc. bug fixes.
*/
//! Primary namespace for comet. Includes source and libraries.
namespace comet {
//! Namespace for comet implementation details.
/*! \internal
*/
namespace impl {
}
}
/** \defgroup Misc Miscelaneous utility classes.
*@{
*/
//@}
/** \defgroup COMType Com type wrappers.
*@{
*/
//@}
/*!\defgroup WinUtil Windows utility classes.
*@{
*/
//@}
#endif

View file

@ -0,0 +1,316 @@
/** \file
* Common utility classes wrappers.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_COMMON_H
#define COMET_COMMON_H
#include <comet/config.h>
#include <comet/interface.h>
#include <wtypes.h>
namespace comet {
class uuid_t;
template<typename Itf>class com_ptr;
namespace impl {
template<typename T> T* bad_alloc_check(T* x)
{
if (!x) throw std::bad_alloc();
return x;
}
/** Implementation struct for auto_attach.
* \internal
*/
template<typename T> class auto_attach_t
{
public:
explicit auto_attach_t(const T& v) : val_(v) {};
const T& get() const { return val_; }
private:
const T& val_;
auto_attach_t& operator=(const auto_attach_t&);
};
// Forward declare all these - only used if we actually WANT a
// safearray.
/** Safearray traits for the given type.
* \internal
*/
template<typename T> struct sa_traits;
/** Safearray iterator for the given type.
* \internal
*/
template<typename S,typename T> class sa_iterator;
/** Safearray const traits for the given type.
* \internal
*/
template<typename T> struct const_traits;
/** Safearray non-const traits for the given type.
* \internal
*/
template<typename T> struct nonconst_traits;
enum sa_traits_check_type { stct_features_ok, stct_vt_ok, stct_iid_ok };
enum sa_traits_extras_type { stet_null, stet_record, stet_iid };
// Interface traits are needed by all interfaces so that we can create
// safearrays of the types.
template<typename INTERFACE, VARTYPE VT, long FEATURE_FLAG>
struct interface_sa_traits
{
enum { vt = VT };
enum { check_type = stct_iid_ok };
enum { extras_type = stet_iid };
typedef INTERFACE* raw;
typedef com_ptr<INTERFACE> value_type;
typedef com_ptr<INTERFACE> & reference;
typedef const com_ptr<INTERFACE> & const_reference;
static reference create_reference(raw& x) { return *reinterpret_cast<com_ptr< INTERFACE>*>(&x); }
static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const com_ptr< INTERFACE >*>(&x); }
typedef nonconst_traits<com_ptr<INTERFACE> > nct;
typedef sa_iterator<com_ptr<INTERFACE>, nct > iterator;
typedef sa_iterator<com_ptr<INTERFACE>, const_traits<com_ptr<INTERFACE> > > const_iterator;
static bool are_features_ok(unsigned short f) { return (f & FEATURE_FLAG) != 0 && (f & FADF_HAVEIID) != 0; }
static const uuid_t& iid() { return uuidof<INTERFACE>(); }
};
/** Basic safearray traits - used by enums.
* \internal
*/
template<typename T, VARTYPE VT> struct basic_sa_traits
{
enum { vt = VT };
enum { check_type = stct_vt_ok };
enum { extras_type = stet_null };
typedef T raw;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
static reference create_reference(T& x) { return x; }
static const_reference create_const_reference(T& x) { return x; }
typedef T* iterator;
typedef const T* const_iterator;
static bool are_features_ok(unsigned short) { return true; }
};
}
/*! \addtogroup COMType
*/
//@{
/// Used to attach a raw parameter to a wrapper.
template<typename T> impl::auto_attach_t<T> auto_attach(const T& t) { return impl::auto_attach_t<T>(t); }
// template<typename T, typename U> inline T up_cast(const U& u, T* = 0) { return u; }
/*! VARIANT_BOOL to bool [in] converter.
* This is used by the generated wrappers.
*/
inline VARIANT_BOOL bool_in(bool x) { return x ? COMET_VARIANT_TRUE : COMET_VARIANT_FALSE; }
/** \class bool_out common.h comet/common.h
* VARIANT_BOOL to bool [out] converter.
* This is used by the generated wrappers.
*/
class bool_out {
public:
operator VARIANT_BOOL*() { return &vb_; }
bool_out(bool& b) : b_(b) {}
~bool_out() { b_ = vb_ ? true : false; }
private:
bool_out &operator=( const bool_out &);
VARIANT_BOOL vb_;
bool& b_;
};
namespace impl {
class bool_adapter_t {
public:
bool_adapter_t(VARIANT_BOOL* p) : pb_(p) { b_ = *pb_ ? true : false; }
~bool_adapter_t() { *pb_ = b_ ? COMET_VARIANT_TRUE : COMET_VARIANT_FALSE; }
bool& ref() { return b_; }
private:
bool_adapter_t(const bool_adapter_t&);
bool_adapter_t& operator=(const bool_adapter_t&);
VARIANT_BOOL* pb_;
bool b_;
};
}
/** \class bool_inout common.h comet/common.h
* VARIANT_BOOL to bool [in,out] converter.
* This is used by the generated wrappers.
*/
class bool_inout {
public:
operator VARIANT_BOOL*() { return &vb_; }
bool_inout(bool& b) : b_(b), vb_(b ? COMET_VARIANT_TRUE : COMET_VARIANT_FALSE) {}
~bool_inout() { b_ = vb_ ? true : false; }
private:
bool_inout &operator=(const bool_inout &);
VARIANT_BOOL vb_;
bool& b_;
};
/** \class variant_bool_t common.h comet/common.h
* VARIANT_BOOL wrapper for structs.
* Stands in place of a VARIANT_BOOL in a struct, and behaves like a bool.
* This is imporant as sizeof(VARIANT_BOOL) != sizeof(bool).
*/
class variant_bool_t
{
VARIANT_BOOL vb_;
public:
/// \name Constructors.
//@{
variant_bool_t(): vb_(COMET_VARIANT_FALSE) {}
variant_bool_t(const impl::auto_attach_t<VARIANT_BOOL> &b) : vb_(b.get()) {}
variant_bool_t(bool b) : vb_(b?COMET_VARIANT_TRUE:COMET_VARIANT_FALSE) {}
//@}
/// \name Assignment operators.
//@{
variant_bool_t &operator=( bool b) { vb_ = b?COMET_VARIANT_TRUE:COMET_VARIANT_FALSE; return *this;}
variant_bool_t &operator=( const impl::auto_attach_t<VARIANT_BOOL> &b) { vb_ = b.get(); return *this; }
//@}
/// \name Boolean operators.
//@{
operator bool() const{ return vb_!= COMET_VARIANT_FALSE; }
bool operator !() const { return vb_== COMET_VARIANT_FALSE; }
bool operator==( variant_bool_t vb) const { return vb.vb_ == vb_; }
bool operator!=( variant_bool_t vb) const { return vb.vb_ != vb_; }
//@}
/// \name Bitwise operators
//@{
variant_bool_t operator~() const { variant_bool_t temp(*this); temp.vb_ = (VARIANT_BOOL)~(temp.vb_); return temp; }
variant_bool_t &operator&=( const variant_bool_t &b) { vb_ &= b.vb_; return *this; }
variant_bool_t &operator|=( const variant_bool_t &b) { vb_ |= b.vb_; return *this; }
variant_bool_t &operator^=( const variant_bool_t &b) { vb_ ^= b.vb_; return *this; }
variant_bool_t operator&( const variant_bool_t &b)const { variant_bool_t temp(*this); temp.vb_ &= b.vb_; return temp; }
variant_bool_t operator|( const variant_bool_t &b)const { variant_bool_t temp(*this); temp.vb_ |= b.vb_; return temp; }
variant_bool_t operator^( const variant_bool_t &b)const { variant_bool_t temp(*this); temp.vb_ ^= b.vb_; return temp; }
//@}
/// \name bool operators
//@{
bool operator&( bool b)const { return b & operator bool(); }
bool operator|( bool b)const { return b | operator bool(); }
bool operator^( bool b)const { return b ^ operator bool(); }
//@}
static const variant_bool_t &create_const_reference(const VARIANT_BOOL &vb) { return reinterpret_cast<const variant_bool_t &>(vb); }
static variant_bool_t &create_reference(VARIANT_BOOL &vb) { return reinterpret_cast<variant_bool_t &>(vb); }
///\name Raw accessors
//@{
VARIANT_BOOL in() { return vb_; }
VARIANT_BOOL *out() { return &vb_; }
VARIANT_BOOL *inout() { return &vb_; }
//@}
/** Allow treating of class as a bool *.
* \sa bool_ptr()
*/
class bool_pointer_t
{
friend class variant_bool_t;
protected:
bool_pointer_t( VARIANT_BOOL &vb) : vb_(vb), b_( vb != COMET_VARIANT_FALSE) {}
public:
~bool_pointer_t() { vb_ = b_ ? COMET_VARIANT_TRUE: COMET_VARIANT_FALSE; }
operator bool*(){ return &b_; }
operator const bool*()const{ return &b_; }
private:
bool_pointer_t &operator=(const bool_pointer_t &);
bool b_;
VARIANT_BOOL &vb_;
};
/** Return a class that stands in for a bool *.
Should be used in place of operator & for passing in to a bool * function.
\code
variant_bool_t vb;
SomeFunc(vb.bool_ptr());
\endcode
*/
bool_pointer_t bool_ptr()
{
return bool_pointer_t(vb_);
}
const bool_pointer_t bool_ptr() const
{
return bool_pointer_t(const_cast<VARIANT_BOOL &>(vb_));
}
friend class bool_reference_t;
/** Allow efficient choosing between a bool& and a variant_bool&.
*/
class bool_reference_chooser_t
{
friend class variant_bool_t;
variant_bool_t &vbt_;
protected:
bool_reference_chooser_t(variant_bool_t &vbt):vbt_(vbt) {}
private:
bool_reference_chooser_t &operator=(const bool_reference_chooser_t &);
public:
inline operator variant_bool_t&() { return vbt_;}
inline operator const variant_bool_t&()const { return vbt_;}
};
/** Allow treating of a class as a bool &.
* \sa bool_ref()
*/
class bool_reference_t : protected bool_pointer_t
{
public:
bool_reference_t( bool_reference_chooser_t &brc )
: bool_pointer_t(*static_cast<variant_bool_t&>(brc).inout())
{}
operator bool &(){ return tmp; /*return * (bool_pointer_t::operator bool*());*/ }
operator const bool &()const { return *(bool_pointer_t::operator const bool*()); }
bool tmp;
};
/** Return a class that stands in for a bool & or a variant_bool_t &.
*/
bool_reference_chooser_t bool_ref()
{
return bool_reference_chooser_t(*this);
}
const bool_reference_chooser_t bool_ref() const
{
return bool_reference_chooser_t(const_cast<variant_bool_t &>(*this));
}
};
//@}
} // namespace
#endif

View file

@ -0,0 +1,243 @@
/** \file
* Included by all comet headers to provide compiler-specific
* configuration.
*/
/*
* Copyright © 2000-2002 Sofus Mortensen
* Copyright (C) 2013 Alexander Lamaison <alexander.lamaison@gmail.com>
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_CONFIG_H
#define COMET_CONFIG_H
#define COMET_MAJOR_VER 2
#define COMET_BUILDTYPE gamma
#define COMET_MINOR_VER 1
#define COMET_BUILD 20131017
#ifndef COMET_BUILD_VERSION_ONLY
#ifndef COMET_NO_DECLSPEC_PROPERTY
#define COMET_ALLOW_DECLSPEC_PROPERTY
#endif // COMET_NO_DECLSPEC_PROPERTY
#pragma warning(disable : 4786)
#pragma warning(disable : 4042)
#pragma warning(disable : 4290)
#pragma warning(disable : 4710)
#ifdef _lint // PC/Lint has a few problems with comet.
# if !defined(_MSC_VER) || _MSC_VER >= 1300
#define COMET_PARTIAL_SPECIALISATION
#else
#endif
#define COMET_NESTED_TEMPLATES
#define COMET_GOOD_RECURSIVE_STRUCT
#define COMET_CONST_MEMBER_INIT
#define COMET_GUID_BASE GUID
#define COMET_STD_ITERATOR
#define COMET_NO_POINTER_CHECKING
#define COMET_STD_SWAP_NOTHROW throw()
#define COMET_TL_TRUNC
#else
//VC 7.1 support partial specialization
#ifdef _MSC_VER
#endif
#ifdef __ICL
# define COMET_PARTIAL_SPECIALISATION
# define COMET_NESTED_TEMPLATES
#else
# ifdef _MSC_VER
# if _MSC_VER < 1300
// Versions less than VC7 can't handle the rethrow & catch exception trick.
# define COMET_DISABLE_EXCEPTION_RETHROW_CATCH
# else // _MSC_VER >= 1300
# define COMET_GOOD_RECURSIVE_STRUCT
# define COMET_CONST_MEMBER_INIT
# if _MSC_VER >= 1310
# define COMET_PARTIAL_SPECIALISATION
# define COMET_NESTED_TEMPLATES
# endif
# endif
# endif
#if defined(_UNICODE) && !defined(UNICODE)
#define UNICODE
#endif
#endif
#ifdef __BORLANDC__
#pragma warning(disable: 8027)
#pragma warning(disable: 8026)
#define COMET_PARTIAL_SPECIALISATION
#define COMET_NESTED_TEMPLATES
#define COMET_BROKEN_WTYPES
#define COMET_STD_ITERATOR
#define COMET_STD_SWAP_NOTHROW
#define COMET_GUID_BASE _GUID
#else
#define COMET_STD_SWAP_NOTHROW throw()
#define COMET_GUID_BASE GUID
#endif
#ifdef __CYGWIN__
#define COMET_PARTIAL_SPECIALISATION
#define COMET_NESTED_TEMPLATES
#define COMET_GCC_HEADERS
#define COMET_STD_ITERATOR
#define COMET_TL_TRUNC
#define _T(x) x
// This is not a good idea
// Routines that use _alloca has to be rewritten for __MINGW32__ targets.
// #define _alloca malloc
// WIN32 defines for GCC
#define NONAMELESSUNION
#define NOCOMATTRIBUTE
#endif
#endif
// Use COMET_STRICT_TYPENAME only where MSVC barfs on stricter typename usage
// required by GCC.
#ifdef _MSC_VER
#if _MSC_VER <= 1300
#define COMET_STRICT_TYPENAME
#else
#define COMET_STRICT_TYPENAME typename
#endif
#else
#define COMET_STRICT_TYPENAME typename
#endif
// PRH Feb 26 2001
// Try and determine which version of std::iterator we have.
// The ANSI/ISO compliant one seems to require a compiler
// that supports partial specialisation, as well as an
// ANSI/ISO compliant implementation of the library.
// Unfortunately, there is no __ANSI_STL #define.
// So we guess:
// If we have partial specialisation, and we're using STLPort, then
// its the ANSI/ISO std::iterator, otherwise it is the MSVC 6.0
// iterator.
// If you're using some other decent STL other than STLPort,
// then you'll need to reflect this by ensuring that COMET_STD_ITERATOR
// is defined.
#if _MSC_VER >= 1300 || defined(_CPPLIB_VER)
#define COMET_STD_ITERATOR
#else
#include <iterator>
#ifdef COMET_PARTIAL_SPECIALISATION
// this code to "detect" STLport is stolen from <boost/config.hpp>
//#if __SGI_STL_PORT >= 0x400 || __SGI_STL_PORT >= 0x321 && defined(__STL_USE_NAMESPACES)
#ifdef __SGI_STL
#define COMET_STD_ITERATOR
#else
#ifdef __MINGW32__
__STL_BEGIN_NAMESPACE
template <class _Tp, class _Distance>struct iterator: bidirectional_iterator<_Tp,_Distance>{};
__STL_END_NAMESPACE
#endif // __MINGW32__
#endif
#else
#ifdef _CPPLIB_VER
#define COMET_STD_ITERATOR
#endif
#endif /* COMET_PARTIAL_SPECIALISATION */
#endif
#ifndef ATL_NO_VTABLE
#if _MSC_VER >= 1200
#define ATL_NO_VTABLE __declspec(novtable)
#else
#define ATL_NO_VTABLE
#endif
#endif
#if _MSC_VER <= 1200
//#define COMET_DO_NOT_SPECIALISE_SWAP_IN_STD
#endif
// Intel compiler version 500 sets _MSC_VER to 1200,
// but doesn't seem to like __forceinline
#if _MSC_VER >= 1200 && !defined(__ICL)
#define COMET_FORCEINLINE __forceinline
#else
#define COMET_FORCEINLINE inline
#endif
#ifdef _UNICODE
#ifndef UNICODE
#define UNICODE // UNICODE is used by Windows headers
#endif
#endif
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE // _UNICODE is used by C-runtime/MFC headers
#endif
#endif
// Remove Microsoft's C++ macros
#undef variant_t
#undef bstr_t
#undef com_cast
// Stop subsequent includes of <comutil.h> from #defining variant_t or bstr_t
#ifndef _USE_RAW
#define _USE_RAW
#endif
#ifndef UUID_DEFINED
#define UUID_DEFINED
#endif
#ifndef UUID
#define UUID GUID
#endif
#ifdef uuid_t
#undef uuid_t
#endif
#define COMET_DECLARE_SWAP(TYPE) template<> inline void swap(TYPE &x, TYPE &y)\
{\
x.swap(y);\
}
const unsigned short COMET_VARIANT_TRUE = (unsigned short)(0xffff);
const unsigned short COMET_VARIANT_FALSE = 0;
#define COMET_NOTUSED(x) x
#ifndef COMET_CONST_MEMBER_INIT
# define COMET_CONST_TYPE(vartype, varname,value) enum { varname = value };
# define COMET_CONST_GROUP enum {
# define COMET_CONST_ENTRY(vartype, varname,value) varname = value,
# define COMET_CONST_GROUP_END };
#else
# define COMET_CONST_TYPE(vartype, varname,value) static const vartype varname = value;
# define COMET_CONST_ENTRY(vartype, varname,value) COMET_CONST_TYPE(vartype, varname, value);
# define COMET_CONST_GROUP
# define COMET_CONST_GROUP_END
#endif
#endif // COMET_BUILD_VERSION_ONLY
#endif

436
lib/local/CamCom/comet/cp.h Normal file
View file

@ -0,0 +1,436 @@
/** \file
* Connection-point implementations.
* The thought behind the current implementation was to try and maintain
* connections points accessible from the coclass through the member
* connection_point.
*
* Where multiple connection-points are defined, the member is accessed thus:
* \code
* connection_point_for<IEventInterface>::connection_point
* \endcode
* The default connection point wrapper implementations have a prefix of
* \b Fire_ before the event name.
*/
/*
* Copyright © 2000 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_CP_H
#define COMET_CP_H
#include <comet/config.h>
#include <map>
#include <comet/server.h>
#include <comet/enum.h>
#pragma warning( push )
#pragma warning( disable : 4355 )
/** \page cometconnectionpoints Connection Points.
\section cometconnectionpointssource Connction Point Source
Connection points provide events for comet, and rely on tlb2h (see \ref tlb2husage) to generate
the implementation for each method on the interface.
Then comet::implement_cpc is used to provide IConnectionPointContainer
(which provides the method for finding a particular connection point.
The default implementation of a coclass will inherit of this method by
default, however they can be explicitly referenced to provide
alternate implementations.
The class comet::implement_cpc is templated to an interface list, which
can be constructed with comet::make_list.
\code
class my_class : public simple_object< IFooImpl<my_class>, implement_cpc< make_list<IFooEvent, IBarEvent>::result > >
\endcode
This causes each of the interface in the list of interfaces to be wrapped by a
comet::connection_point_for class which provides the access syntax.
\code
connection_point_for<IFooEvent>::connection_point.Fire_FooMethod( args );
\endcode
Note that \b Fire_ is prepended to each method name.
If there is only one connection point in the list, then the
connection_point_for namespace segregator is not required.
If there is no connection point implementation for the interface, then you should make
sure that it is referenced with a [source] tag by a coclass definition
in the library you are including, and that you are generating server
implementations or forcing it by prepending '*' in a symbol file, see
the \ref wrappergensymbolformat.
\section cometconnectionpointsink Connction Point Sink
In order to prevent the circular references inherent in connection points, the
reference loop must be broken somehow. This is best done by using a contained
member that calls back on the parent class.
The class sink_impl is best used in this circumstance as it contains code for calling
Advise and Unadvise. It inherits from static_object which is designed to be embedded in
a class, and does reference counting on the module and does not destruct itself.
This class is templated to the interface implementation desired, which will
mostly be the 'Impl' class for the interface, but might be a raw COM interface.
In this example we have a class 'MyCoclass' that is sinking the event interface IMyEventImpl which
has a single 'EventHappened' method.
\code
class coclass_MyCoclass : public coclass<MyCoclass>
{
// Private Embedded sink implementation.
struct sink_t : sink_impl<IMyEventImpl>
{
sink_t(coclass_MyCoclass *Parent) :m_parent(Parent) {}
inline void EventHappened( long param_Here ) { m_parent->sink_EventHappened(param_Here); }
coclass_MyCoclass *m_parent; // Non-addref reference.
} m_sink;
public:
coclass_MyCoclass() : m_sink(this) {}
// Set the event source.
void SetEventSource( const com_ptr<IUnknown> &unknown)
{
if (m_sink.is_advised())
m_sink.unadvise();
m_sink.advise( unknown );
}
inline void sink_EventHappened( long param_Here )
{
// Event code goes here
}
};
\endcode
*/
namespace comet {
template<typename Itf> class connection_point;
/*! \addtogroup Interfaces
*/
//@{
/** \class simple_cpc cp.h comet/cp.h
* Implement a simple connection-point container with a single
* connection-point.
* \param Itf The single connection-point interface.
* \sa implement_cpc
*/
template<typename Itf> class ATL_NO_VTABLE simple_cpc : public IConnectionPointContainer
{
public:
typedef IConnectionPointContainer interface_is;
protected:
/// \name IConnectionPointContainer interface
//@{
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints**)
{
return E_NOTIMPL;
}
STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint** ppCP)
{
if (!ppCP) return E_POINTER;
if (riid == uuidof<Itf>()) {
*ppCP = &connection_point;
(*ppCP)->AddRef();
return S_OK;
}
return CONNECT_E_NOCONNECTION;
}
//@}
protected:
simple_cpc() : connection_point(this) {}
connection_point<Itf> connection_point;
};
/** \class connection_point_for cp.h comet/cp.h
* Provide access to implementation for a connection point.
* \relates implement_cpc
*/
template<typename Itf> class connection_point_for
{
public:
connection_point_for(::IUnknown *self) : connection_point(self) {}
connection_point<Itf> connection_point;
};
namespace impl {
/** Find a connection point implementation for a given iid.
* \internal
*/
template<typename ITF_LIST> struct connection_point_finder
{
template<typename T> COMET_FORCEINLINE static ::IConnectionPoint* find_connection_point(T* This, const IID& iid)
{
typedef find_compatibility< COMET_STRICT_TYPENAME ITF_LIST::head > compatible;
if (iid == uuidof<COMET_STRICT_TYPENAME ITF_LIST::head>())
return &((static_cast<connection_point_for< COMET_STRICT_TYPENAME ITF_LIST::head > *>(This))->connection_point) ;
else return connection_point_finder<COMET_STRICT_TYPENAME ITF_LIST::tail>::find_connection_point(This, iid);
}
};
template<> struct connection_point_finder<nil>
{
template<typename T> COMET_FORCEINLINE static ::IConnectionPoint* find_connection_point(T*, const IID&)
{
return 0;
}
};
}
namespace impl {
template<typename ITF_LIST> struct ATL_NO_VTABLE inherit_all_ex_unknown;
#ifdef COMET_GOOD_RECURSIVE_STRUCT
// Remove level of indirection. PC-lint cannot handle it, and MSVC7
// should be ale to.
template<typename ITF_LIST> struct ATL_NO_VTABLE inherit_all_ex_unknown
: public ITF_LIST::head, public inherit_all_ex_unknown<typename ITF_LIST::tail >
{
inherit_all_ex_unknown( ::IUnknown *initParam)
: ITF_LIST::head(initParam), inherit_all_ex_unknown< COMET_STRICT_TYPENAME ITF_LIST::tail >(initParam)
{}
};
template<> struct inherit_all_ex_unknown<nil> { inherit_all_ex_unknown(::IUnknown *) {} };
#else // COMET_GOOD_RECURSIVE_STRUCT
template<typename HEAD, typename ITF_TAIL> struct ATL_NO_VTABLE inherit_all_ex_aux_unknown
: public HEAD, public inherit_all_ex_unknown<ITF_TAIL>
{
inherit_all_ex_aux_unknown( ::IUnknown *initParam)
: HEAD(initParam), inherit_all_ex_unknown<ITF_TAIL>(initParam)
{}
};
// COMET_CONFIG_H is always defined! This is just a trick to get Doxygen to ignore the following declaration that
// otherwise seems to be cause an exception in Doxygen 1.2.8
#ifdef COMET_CONFIG_H
template<typename ITF_LIST> struct ATL_NO_VTABLE inherit_all_ex_unknown
: public inherit_all_ex_aux_unknown<typename ITF_LIST::head,typename ITF_LIST::tail >
{
inherit_all_ex_unknown( ::IUnknown *initParam)
:inherit_all_ex_aux_unknown< COMET_STRICT_TYPENAME ITF_LIST::head, COMET_STRICT_TYPENAME ITF_LIST::tail >(initParam)
{
}
};
template<> struct inherit_all_ex_unknown<nil> { inherit_all_ex_unknown(::IUnknown *) {} };
#endif // COMET_CONFIG_H
#endif // COMET_GOOD_RECURSIVE_STRUCT
}
COMET_WRAP_EACH_DECLARE( connection_point_for)
/** \struct implement_cpc cp.h comet/cp.h
* Implement a connection point container that can handle multiple
* connection points.
* This should be added to the \link comet::make_list list \endlink of implemented interfaces for a coclass as it
* implements IConnectionPointContainer (which will be required for a qi).
*
* The class is used by the default coclass implementation to provide \ref cometconnectionpoints.
*
* \param ITF_LST \link comet::make_list List \endlink of connection points interfaces to implement.
*/
template< typename ITF_LST> struct ATL_NO_VTABLE implement_cpc : public IConnectionPointContainer
, public impl::inherit_all_ex_unknown< COMET_WRAP_EACH(connection_point_for, ITF_LST) >
{
typedef IConnectionPointContainer interface_is;
public:
implement_cpc()
: impl::inherit_all_ex_unknown< COMET_WRAP_EACH(comet::connection_point_for, ITF_LST) >((::IUnknown *)this)
{}
protected:
friend struct impl::connection_point_finder<ITF_LST>;
/// \name IConnectionPointContainer interface
//@{
STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints**)
{
return E_NOTIMPL;
}
STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint** ppCP)
{
if (!ppCP) return E_POINTER;
const IID& iid = riid;
*ppCP = impl::connection_point_finder<ITF_LST>::find_connection_point(this, iid);
if ( *ppCP !=NULL)
{
(*ppCP)->AddRef();
return S_OK;
}
return CONNECT_E_NOCONNECTION;
}
//@}
};
/** \class connection_point_impl cp.h comet/cp.h
* Implements a connection point.
* \param Itf Interface of connection point.
*/
template<typename Itf> class ATL_NO_VTABLE connection_point_impl : public embedded_object< IUnknown, IConnectionPoint >
{
public:
bool is_connected() const
{ return !connections_.empty(); }
protected:
connection_point_impl(::IUnknown* pUnk) : next_cookie_(1), embedded_object< IUnknown, IConnectionPoint >(pUnk) {}
/// \name IConnectionPoint interface
//@{
STDMETHOD(GetConnectionInterface)(IID* pIID)
{
*pIID = uuidof<Itf>();
return S_OK;
}
STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** ppCPC) {
com_ptr<IConnectionPointContainer> p;
p = try_cast(com_ptr< ::IUnknown >(get_parent()));
*ppCPC = com_ptr<IConnectionPointContainer>::detach( p );
return S_OK;
}
STDMETHOD(Advise)(::IUnknown* pUnkSink, DWORD* pdwCookie)
{
try {
connections_[next_cookie_] = try_cast( com_ptr< ::IUnknown >(pUnkSink) );
}
catch (...) {
return CONNECT_E_CANNOTCONNECT;
}
*pdwCookie = next_cookie_++;
return S_OK;
}
STDMETHOD(Unadvise)(DWORD dwCookie)
{
CONNECTIONS::iterator it = connections_.find(dwCookie);
if (it == connections_.end()) return CONNECT_E_NOCONNECTION;
connections_.erase(it);
return S_OK;
}
STDMETHOD(EnumConnections)(IEnumConnections** ppEnum)
{
try {
*ppEnum = com_ptr<IEnumConnections>::detach( stl_enumeration<IEnumConnections>::create(connections_, get_unknown()) );
} catch (...) {
return E_FAIL;
}
return S_OK;
}
//@}
typedef std::map<DWORD, com_ptr<Itf> > CONNECTIONS;
CONNECTIONS connections_;
private:
UINT next_cookie_;
};
/** \class sink_impl cp.h comet/cp.h
* Implement a sink for a connection pointer.
* \param Itf interface to implement.
*/
template<typename Itf> class ATL_NO_VTABLE sink_impl : public static_object<Itf>
{
public:
/** Advise this object as sinking connections from \p t.
*/
void advise(const com_ptr< ::IUnknown>& t)
{
if (ptr_) throw std::runtime_error("Cannot double advise.");
com_ptr<IConnectionPointContainer> cpc( try_cast(t) );
IConnectionPoint* cp;
cpc->FindConnectionPoint( uuidof<Itf>(), &cp) | raise_exception;
HRESULT hr = cp->Advise(static_cast< ::IUnknown* >(static_cast<Itf*>(this)), &cookie_);
cp->Release();
hr | raise_exception;
ptr_ = t;
}
/** Unadvise this interface from object \p t.
*/
void unadvise()
{
if (ptr_) {
com_ptr<IConnectionPointContainer> cpc( try_cast(ptr_) );
IConnectionPoint* cp;
cpc->FindConnectionPoint( uuidof<Itf>(), &cp) | raise_exception;
HRESULT hr = cp->Unadvise(cookie_);
cookie_ = 0;
ptr_ = 0;
cp->Release();
hr | raise_exception;
}
}
/** Get event object.
*/
com_ptr< ::IUnknown> object()
{
return ptr_;
}
/** Return true if advised.
*/
bool is_advised()
{
return !ptr_.is_null();
}
protected:
sink_impl() : cookie_(0) {}
~sink_impl() { unadvise(); }
private:
DWORD cookie_;
com_ptr< ::IUnknown> ptr_;
};
//@}
}
#pragma warning( pop )
#endif

View file

@ -0,0 +1,118 @@
/** \file
* Connection-point traits.
*/
/* Copyright © 2002 Michael Geddes
* Copyright © 2013 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef INCLUDE_COMET_CPTRAITS_H
#define INCLUDE_COMET_CPTRAITS_H
#ifdef _SHOW_INC
#pragma message(" #Include " __FILE__)
#endif
#include <comet/config.h>
#include <comet/error_fwd.h> // raise_exception
#include <Windows.h> // HRESULT
namespace comet
{
/*! \struct cp_throw cptraits.h comet/cptraits.h
* Default 'throw' traits for connection-points.
* \code Usage
* connection_point_for<IMySourceInterface>::connection_point.Fire_MyEvent( arg1, comet::cp_throw());
* \endcode
*/
struct cp_throw
{
/// Constructor - called before iterating over the connection-points.
cp_throw() : _hr_(S_OK) { }
/// Destructor - called after iterating over all the connection-points.
~cp_throw() { _hr_ | raise_exception ; }
/*! Called when a connection point fails.
* Can also be used to remember the hresult for the destructor.
*
* \retval true Cause the on_fail method to be called.
* \retval false Ignore the failure.
*/
bool check_fail(HRESULT hr)
{
if( FAILED(hr) )
_hr_ = hr;
return false;
}
/*! Called when check_fail returns true.
* \param par_connects Reference to the STL container containing the connection-points.
* \param par_it The iterator of the failed connection-point.
*/
template<typename CONNECTIONS>
static bool on_fail(CONNECTIONS &par_connects, const typename CONNECTIONS::iterator & par_it)
{
COMET_NOTUSED(par_it);
COMET_NOTUSED(par_connects);
return false;
}
protected:
HRESULT _hr_;
};
/*! \struct cp_nothrow_remove cptraits.h comet/cptraits.h
* Traits for connection-points, errors cause the connection-point to auto-remove.
* \code
* connection_point_for<IMySourceInterface>::connection_point.Fire_MyEvent( arg1, comet::cp_nothrow_remove());
* \endcode
* \sa cp_throw
*/
struct cp_nothrow_remove
{
//! Called when a connection point fails.
bool check_fail( HRESULT _hr_) throw() { return FAILED(_hr_); }
//! Called when check_fail returns true.
template<typename CONNECTIONS>
static bool on_fail(CONNECTIONS &par_connects, const typename CONNECTIONS::iterator &par_it ) throw()
{
try{ par_connects.erase(par_it); }catch(...) {}
return false;
}
};
/*! \struct cp_nothrow cptraits.h comet/cptraits.h
* Tratis for connection-points, errors are ignored.
* \code
* connection_point_for<IMySourceInterface>::connection_point.Fire_MyEvent( arg1, comet::cp_nothrow());
* \endcode
* \sa cp_throw
*/
struct cp_nothrow
{
//! Called when a connection point fails.
bool check_fail( HRESULT _hr_) throw() { return FAILED(_hr_); }
//! Called when check_fail returns true.
template<typename CONNECTIONS>
static bool on_fail(CONNECTIONS &par_connects, const typename CONNECTIONS::iterator &par_it ) throw() { return false; }
};
}
#endif /* INCLUDE_COMET_CPTRAITS_H */

View file

@ -0,0 +1,474 @@
/** \file
* Currency wrapper.
*/
/* Copyright © 2001 Michael Geddes, Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_CURRENCY_H
#define COMET_CURRENCY_H
#include <comet/config.h>
#include <comet/error_fwd.h>
#include <comet/assert.h>
#include <wtypes.h>
#include <iostream>
#include <algorithm>
namespace comet
{
class bstr_t;
// currency_t
///////////////
/*! \addtogroup COMType
*/
//@{
/** Wrapper for CURRENCY type.
* CURRENCY is a fixed point (to 4 decimal places) 64 bit value.
*/
class currency_t
{
public:
/// Default Constructor
currency_t() throw() { cy_.int64 = 0; }
/// CY constructor.
currency_t(const CY &cy): cy_(cy) { }
/// Double Conversion constructor.
explicit currency_t(double val)
{
VarCyFromR8(val,&cy_) | raise_exception;
}
#if 0
// //! Construct currency from CY/CURRENCY.
// /*!
// Takes ownership of specified CY value. To prevent misuse the CY must be wrapped using auto_attach.
//
// \code
// currency_t cy( auto_attach( myCY ) );
// \endcode
//
// \param cyVal
// Value to initialise currency_t from.
// */
// currency_t( const impl::auto_attach_t<CY> &cyVal) throw() : cy_(cyVal.get())
// {}
#endif //0
/// Long Conversion constructor.
currency_t( long val )
{
VarCyFromI4(val,&cy_) | raise_exception;
}
currency_t( int val )
{
VarCyFromI4(val,&cy_) | raise_exception;
}
void swap(currency_t& c) throw()
{
std::swap(cy_, c.cy_);
}
static const currency_t& create_const_reference(const CY& s) throw()
{ return *reinterpret_cast<const currency_t*>(&s); }
static currency_t& create_reference(CY& s) throw()
{ return *reinterpret_cast<currency_t*>(&s); }
//! \name Assignment Operators
//@{
currency_t &operator=(double newVal)
{
currency_t c( newVal );
swap(c);
return *this;
}
currency_t &operator=(long newVal)
{
currency_t c( newVal );
swap(c);
return *this;
}
currency_t &operator=(int newVal)
{
currency_t c( newVal );
swap(c);
return *this;
}
currency_t &operator=(const tagCY &newVal) throw()
{
cy_ = newVal;
return *this;
}
//@}
/// \name Mathematical Operators
//@{
currency_t &operator+=(const currency_t &cy)
{
currency_t c( *this + cy );
swap(c);
return *this;
}
currency_t &operator-=(const currency_t &cy)
{
currency_t c( *this - cy );
swap(c);
return *this;
}
currency_t &operator*=(const currency_t &cy)
{
currency_t c( *this * cy );
swap(c);
return *this;
}
currency_t &operator*=(long cy)
{
currency_t c( *this * cy );
swap(c);
return *this;
}
currency_t &operator*=(int val)
{
return operator*=((long)val);
}
currency_t &operator*=(double val)
{
cy_.int64 = (LONGLONG)(cy_.int64 * val);
return *this;
}
currency_t &operator/=(int val) const
{
return operator/=((long)val);
}
currency_t &operator/=(long val)
{
if(!valid())
{
// Check for invalid number
return *this;
}
// Check for divide by 0
if (val == 0)
{
// Set to maximum negative value
cy_.Hi = 0x80000000;
cy_.Lo = 0x00000000;
return *this;
}
cy_.int64/=val;
return *this;
}
currency_t operator+(const currency_t &cy)const
{
currency_t rv;
VarCyAdd(cy_,cy.cy_,&rv.cy_) | raise_exception ;
return rv;
}
currency_t operator-(const currency_t &cy)const
{
currency_t rv;
VarCySub(cy_,cy.cy_,&rv.cy_) | raise_exception ;
return rv;
}
currency_t operator*(const currency_t &cy)const
{
currency_t rv;
VarCyMul(cy_,cy.cy_,&rv.cy_) | raise_exception ;
return rv;
}
currency_t operator*(long cy)const
{
currency_t rv;
VarCyMulI4(cy_,cy,&rv.cy_) | raise_exception;
return rv;
}
currency_t operator*(int cy)const
{
return operator *((long)cy);
}
currency_t operator*(double cy) const
{
currency_t val(*this);
val *=cy;
return val;
}
/// Calculate approximate ratio.
double operator/(const currency_t &cy)const
{
return ((double)cy_.int64 /(double)cy.cy_.int64);
}
/// Divide by int.
currency_t operator/(int val) const
{
return operator/((long)val);
}
/// Divide by long.
currency_t operator/(long val) const
{
currency_t tmp(cy_);
tmp/=val;
return tmp;
}
/// Divide by double
double operator/(double val) const
{
if(!valid())
{
// Check for invalid number
throw std::invalid_argument("Invalid divide");
}
// Check for divide by 0
if (val == 0)
{
throw std::overflow_error("Divide by 0");
}
return cy_.int64/(val*10000);
}
/// Unary negate.
currency_t operator-()const
{
currency_t cy;
VarCyNeg(cy_,&(cy.cy_)) | raise_exception;
return cy;
}
//@}
/** Rounds the value to specified number of decimal places.
* \param decimals Number of places to round to.
*/
currency_t &round_to(int decimals)
{
VarCyRound(cy_,decimals,&cy_) | raise_exception;
return *this;
}
/// \name Logical Operators
//@{
bool operator!=(const currency_t &cy) const { return cmp(cy)!=0; }
bool operator!=(double val) const{ return cmp(val)!=0; }
bool operator==(const currency_t &cy) const { return cmp(cy)==0; }
bool operator==(double val) const{ return cmp(val)==0; }
bool operator<=(const currency_t &cy) const{ return cmp(cy)<=0; }
bool operator<=(double val) const{ return cmp(val)<=0; }
bool operator>=(const currency_t &cy) const{ return cmp(cy)>=0; }
bool operator>=(double val) const{ return cmp(val)>=0; }
bool operator<(const currency_t &cy) const{ return cmp(cy)<0; }
bool operator<(double val) const{ return cmp(val)<0; }
bool operator>(const currency_t &cy) const{ return cmp(cy)>0; }
bool operator>(double val) const{ return cmp(val)>0; }
//@}
/** Compares the value like strcmp.
* \param cy Number to be compared.
*/
int cmp(const currency_t &cy) const
{
return _cmpResult(VarCyCmp(cy_,cy.cy_));
}
/** Compares the value like strcmp.
* \param cy Number to be compared.
*/
int cmp(double cy) const
{
return _cmpResult(VarCyCmpR8(cy_,cy));
}
//! \name Access converters
//@{
tagCY get() const { return cy_;}
tagCY in() const { return cy_;}
tagCY *in_ptr() const { return const_cast<CY*>(&cy_);}
tagCY *out() { return &cy_;}
tagCY *inout() { return &cy_;}
//@}
#if 0
friend std::ostream &operator <<(std::ostream &str, const currency_t &val)
{
std::string strval=val.format( 1, str.precision(), str.width() );
return str<< strval.c_str();
}
#endif
friend
std::basic_ostream<char> &operator<<(std::basic_ostream<char> &str, const currency_t &val)
{
std::basic_string<char> strval;
val.do_format(strval, 1, str.precision(), str.width() );
return str << strval.c_str();
}
friend
std::basic_ostream<wchar_t> &operator<<(std::basic_ostream<wchar_t> &str, const currency_t &val)
{
std::basic_string<wchar_t> strval;
val.do_format(strval, 1, str.precision(), str.width() );
return str << strval.c_str();
}
//! Format the string with the given digits, precision and width.
std::basic_string<TCHAR> format(
std::streamsize mindigits=0, std::streamsize minprecision=0,
std::streamsize width=0) const
{
std::basic_string<TCHAR> strval;
do_format(strval, mindigits, minprecision, width);
return strval;
}
//! Parse the string to a currency.
currency_t &parse( const bstr_t &str, LCID locale =::GetThreadLocale() );
/* {
VarCyFromStr( str.in(), locale, 0, &cy_ ) | raise_exception;
return *this;
}*/
protected:
/** Return a string representation of the value.
* \param val output string (return values can't automatically detect template arguments)
* \param mindigits Minimum number before decimal point.
* \param minprecision Minimum number after decimal point.
* \todo Obey ostream formats for: fillchar(), ios_base::left, ios_base::internal, ios_base::showpos
*/
template <typename CH>
void do_format(
std::basic_string<CH>& val, std::streamsize mindigits,
std::streamsize minprecision, std::streamsize /*width*/) const
{
COMET_ASSERT(mindigits>=0 && minprecision >=0 );
if(minprecision> 4) minprecision =4;
// Add in the 4 fixed decimal points
std::streamsize pr =
((0 <= minprecision && minprecision <=4) ?
(4-minprecision) : 0);
mindigits+=4;
val.erase();
val.reserve(22);
LONGLONG value=cy_.int64;
bool neg=value<0;
if(neg)
{
value=-value;
}
// Put in the digits backwards
std::streamsize digit=0;
bool output=false;
while(value !=0 || digit < mindigits)
{
CH dig=CH(value%10);
if(output || true==(output= (dig >0 || digit>=pr))) // Once 'output' is set - output everything.
{
val+=(CH('0'+dig));
}
if(++digit == 4)
{
val+=CH('.');
output=true;
}
value/=10;
}
if(neg)
{
val+=CH('-');
}
// Now reverse the digits
std::reverse(val.begin(), val.end());
}
public:
/// Returns true if this is a valid number
bool valid() const throw()
{ return !(cy_.Hi==(long)0x80000000 && cy_.Lo==0);}
/// Detaches the CY value. Provided for consistancy.
CY detach() throw()
{
CY val = cy_;
cy_.int64 = 0;
return val;
}
/// Detaches the CY value. Provided for consistancy.
static CY detach(currency_t& cy) throw()
{
return cy.detach();
}
private:
CY cy_;
static int _cmpResult(HRESULT hr)
{
if(SUCCEEDED(hr))
{
switch(hr)
{
case VARCMP_LT:
return -1;
case VARCMP_EQ :
return 0;
case VARCMP_GT:
return 1;
case VARCMP_NULL:
COMET_ASSERT(!"What do we do with this?");
}
}
else
{
hr | raise_exception;
}
return 0; // shut the compiler up
}
};
//@}
}
#endif // COMET_CURRENCY_H

View file

@ -0,0 +1,396 @@
/** \file
* Date wrapper (part of datetime).
*/
/*
* Copyright © 2004 Michael Geddes
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef INCLUDE_COMET_DATE_H
#define INCLUDE_COMET_DATE_H
#ifdef _SHOW_INC
#pragma message(" #Include " __FILE__)
#endif
#include <comet/datetime.h>
namespace comet
{
/*! \addtogroup Misc
*/
//@{
//! Wrapper for a date only class.
/**This is based on an integer version of DATE, except that it is an
* absolute offset from 1/1/0.
*/
struct dateonly_t : protected impl::datetime_base<long>
{
/// constructor
dateonly_t() { dt_ = 0; }
/// Construct from a datetime_t.
explicit dateonly_t( const datetime_t &dt)
{
if (dt == dt_invalid )
dt_ = dt_invalid_;
else if (dt == dt_null)
dt_ = dt_null_;
else
dt_ = split_oledate_as_absdate_( dt.get());
}
/// Attach from a long.
dateonly_t( const impl::auto_attach_t<long> &dateval)
{
dt_ = dateval.get();
}
/// Get the raw 'long' value.
long get() const { return dt_; }
dateonly_t &operator=(const impl::auto_attach_t<long> & dateval)
{
dt_ = dateval.get();
return *this;
}
/// Initialise as invalid.
dateonly_t( dt_invalid_t ) { dt_ = dt_invalid_; }
/// Initialise as null.
dateonly_t( dt_null_t ) { dt_ = dt_null_; }
/// Initialise as zero.
dateonly_t( dt_zero_t) { dt_ = 0; }
/// Construct from year/month/day.
dateonly_t( int year, int month, int day )
{
if (!absdate_from_date_( &dt_, year, month, day))
set_invalid_();
}
/// Get a 'NULL' datetime.
static dateonly_t get_null() { return dateonly_t( dt_null_ ); }
/// Get a 'zero' datetime.
static dateonly_t get_zero() { return dateonly_t( 0 ); }
/// Return today.
static dateonly_t today()
{
return dateonly_t(datetime_t::now());
}
/// Return today (UTC).
static dateonly_t today_utc()
{
return dateonly_t(datetime_t::now_utc());
}
/// Return year/month/day values.
void split(int *year, int *month, int *day) const
{
if(!good() || ! date_from_absdate_( dt_, year, month, day))
throw datetime_exception("Invalid Date");
}
/** Set date part as year/month/day.
* \param year Year (from year 0 - as in 2000).
* \param month Month of year (1-based).
* \param day Day of month (1-based).
* \retval true Successfully set date.
* \retval false Conversion unsuccessful - date not set.
*/
bool set_date( int year, int month, int day)
{
return absdate_from_date_( &dt_, year, month, day);
}
/// Convert to datetime.
operator datetime_t() const
{
if (!good()) return datetime_t((DATE)dt_);
return datetime_t(join_absdate_as_oledate_( dt_, 0));
}
/// \name Access date parts.
//@{
/// Year.
int year() const
{
int year;
split(&year,NULL,NULL);
return year;
}
/// Month of year (1-based)
int month() const
{
int year,month,day;
split(&year,&month,&day);
return month;
}
/// Day of month (1-based)
int day() const
{
int year,month,day;
split(&year,&month,&day);
return day;
}
/// The day of week.
datetime_t::day_of_week dow() const
{
int wday;
if(!good() || ! dow_from_absdate_( dt_, &wday))
throw datetime_exception("Invalid Date");
return datetime_t::day_of_week(wday);
}
/// Day of the year (0 -based)
int year_day() const
{
if (good())
{
int y,m,d;
date_from_absdate_(dt_, &y,&m,&d);
long firstday;
if ( absdate_from_date_(&firstday, y, 1, 1))
return 1 + ( dt_ - firstday);
}
throw datetime_exception("Invalid Date");
}
/// Days in the month.
int days_in_month() const
{
int year,month,day;
split(&year,&month,&day);
return days_in_month(year,month);
}
//@}
/** Add specified number of months.
* If the day is not valid, force to the last day in the month.
*/
dateonly_t &add_months(int inc_months)
{
int year,month,day;
split(&year,&month,&day);
long months = (month-1)+(year*12)+inc_months;
long quot,rem;
quot = months/12;
rem = months%12;
set_date( quot, rem+1, day);
return *this;
}
/// Add specified number of years.
dateonly_t &add_years(int inc_years)
{
int year,month,day;
split(&year,&month,&day);
set_date( year+inc_years, month, day);
return *this;
}
///\name Comparison operators
//@{
bool operator==(const dateonly_t& date) const { return date.dt_ == dt_; }
bool operator!=(const dateonly_t& date) const{ return date.dt_ != dt_; }
bool operator<(const dateonly_t& date) const
{
COMET_ASSERT( good() );
COMET_ASSERT( date.good() );
return dt_ < date.dt_;
}
bool operator>(const dateonly_t& date) const
{
COMET_ASSERT( good() );
COMET_ASSERT( date.good() );
return dt_ > date.dt_;
}
bool operator<=(const dateonly_t& date) const
{
COMET_ASSERT( good() );
COMET_ASSERT( date.good() );
return dt_ <= date.dt_;
}
bool operator>=(const dateonly_t& date) const
{
COMET_ASSERT( good() );
COMET_ASSERT( date.good() );
return dt_ >= date.dt_;
}
bool operator==(dt_invalid_t) const { return invalid(); }
bool operator!=(dt_invalid_t) const { return !invalid(); }
bool operator==(dt_zero_t) const { return dt_==0; }
bool operator!=(dt_zero_t) const { return dt_!=0; }
bool operator==(dt_null_t) const { return null(); }
bool operator!=(dt_null_t) const { return !null(); }
//@}
///\name Arithmetic operators
//@{
dateonly_t operator+(long dateSpan) const
{
dateonly_t dt(*this);
dt+=dateSpan;
return dt;
}
dateonly_t operator-(long dateSpan) const
{
dateonly_t dt(*this);
dt-=dateSpan;
return dt;
}
dateonly_t& operator+=(long dateSpan)
{
COMET_ASSERT( good() );
dt_ += dateSpan;
return *this;
}
dateonly_t& operator-=(long dateSpan)
{
COMET_ASSERT( good() );
dt_ -= dateSpan;
return *this;
}
long operator-(const dateonly_t& date) const
{
COMET_ASSERT( good() );
COMET_ASSERT( date.good() );
return dt_ - date.dt_;
}
dateonly_t &operator++()
{
COMET_ASSERT( good() );
++dt_;
return *this;
}
dateonly_t operator++(int)
{
COMET_ASSERT( good() );
dateonly_t t(*this);
++dt_;
return t;
}
dateonly_t &operator--()
{
COMET_ASSERT( good() );
--dt_;
return *this;
}
dateonly_t operator--(int)
{
COMET_ASSERT( good() );
dateonly_t t(*this);
--dt_;
return t;
}
//@}
/// return true if the date is marked 'invalid'.
inline bool invalid() const { return dt_ == ( dt_invalid_); }
/// Return true if the date is marked 'null'
inline bool null() const { return dt_ == ( dt_null_); }
/// return true if date is zero
inline bool zero() const { return dt_ == 0; }
/// Return true if the date is usable.
inline bool good() const
{
switch (dt_)
{
case 0: case dt_invalid_: case dt_null_: return false;
default: return true;
}
}
/** Format as bstr.
* \param flags Format (can be or-ed). All format_flags are valid.
* \param locale Locale ID (default to User Default.
*/
bstr_t format( datetime_t::format_flags flags = datetime_t::ff_default , LCID locale = LOCALE_USER_DEFAULT) const
{
flags = datetime_t::format_flags((flags | datetime_t::ff_date_only) & ~datetime_t::ff_time_only);
bstr_t strDate;
if (null() || invalid())
return strDate;
DATE dt = join_absdate_as_oledate_( dt_, 0);
VarBstrFromDate(dt, locale, flags, strDate.out()) | raise_exception;
return strDate;
}
/** Parse bstring to a datetime_t.
* \param val String to parse.
* \param flags valid format_flags are: ff_default, ff_system_locale, ff_hijri, ff_time_only, ff_date_only
* \param locale Locale to use. Default \p locale is the user default.
*/
dateonly_t &parse( const bstr_t &val, datetime_t::format_flags flags = datetime_t::ff_default, LCID locale = LOCALE_USER_DEFAULT)
{
flags = datetime_t::format_flags((flags | datetime_t::ff_date_only) & ~datetime_t::ff_time_only);
DATE dt;
VarDateFromStr( val.in(), locale, flags, &dt) | raise_exception;
dt_ = split_oledate_as_absdate_( dt);
return *this;
}
/** Format as basic_string.
* \param fmt See system documentation for strftime for details.
*/
template<typename CHAR>
std::basic_string<CHAR> format( const std::basic_string<CHAR> &fmt ) const
{
return format(fmt.c_str());
}
/** Format as basic_string.
* \param fmt See system documentation for strftime for details.
*/
template<typename CHAR>
std::basic_string<CHAR> format( const CHAR *fmt ) const
{
// Just use datetime_t to handle this.
datetime_t dt(*this);
return dt.format(fmt);
}
/// Stream operator.
friend
std::basic_ostream<char> &operator<<(std::basic_ostream<char> &os, const dateonly_t &val)
{
os << val.format();
return os;
}
/// Stream operator.
friend
std::basic_ostream<wchar_t> &operator<<(std::basic_ostream<wchar_t> &os, const dateonly_t &val)
{
os << val.format();
return os;
}
static inline int days_in_month(int year, int month)
{
return impl::datetime_base<long>::days_in_month(year,month);
}
protected:
explicit dateonly_t(long l) { dt_ = l; }
};
//@}
};
#endif /* INCLUDE_COMET_DATE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,675 @@
/** \file
* Provides dispatch driver via wrap_t< ::IDispatch>
* Provides dynamic implementation of IDispatch via dynamic_dispatch.
*/
/*
* Copyright © 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_DISPATCH_H
#define COMET_DISPATCH_H
#include <comet/ptr.h>
#include <map>
namespace comet {
/*! \addtogroup Interfaces
*/
//@{
/** Specialisation of wrap_t for IDispatch.
* Implements wrappers for the call-by name and call-by dispid for IDispatch methods
* and properties. The wrapper supports properties with up to 3 arguments and methods
* with up to 4 arguments.
* \code
com_ptr<IDispatch> disp( my_dual_interface);
variant_t val = disp->get(L"Name");
* \endcode
* See \ref cometcomptrsmartwrapper for details on wrap_t.
*/
template<> struct wrap_t< ::IDispatch>
{
/** Get property by dispid.
*/
variant_t get(DISPID id)
{
VARIANT result;
VARIANT* vars = 0;
DISPPARAMS disp = { vars, 0, 0, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
/** Get property by name.
*/
variant_t get(const wchar_t* name)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return get(id);
}
/** Get property by dispid with 1 argument.
*/
variant_t get(DISPID id, const variant_t& a0)
{
VARIANT result;
VARIANT vars[1]; vars[0] = a0.in();
DISPPARAMS disp = { vars, 0, 1, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
/** Get property by name with 1 argument.
*/
variant_t get(const wchar_t* name, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return get(id, a0);
}
/** Get property by dispid with 2 arguments.
*/
variant_t get(DISPID id, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[2]; vars[0] = a0.in(); vars[1] = a1.in();
DISPPARAMS disp = { vars, 0, 2, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
/** Get property by name with 2 arguments.
*/
variant_t get(const wchar_t* name, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return get(id, a1, a0);
}
/** Get property by dispid with 3 arguments.
*/
variant_t get(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[3]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in();
DISPPARAMS disp = { vars, 0, 3, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
/** Get property by name with 3 arguments.
*/
variant_t get(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return get(id, a2, a1, a0);
}
/** Put property by dispid.
*/
void put(DISPID id, const variant_t& val)
{
VARIANT vars[1]; vars[0] = val.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 1, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
/** Put property by name.
*/
void put(const wchar_t* name, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
put(id, val);
}
/** Put property with 1 argument by dispid.
*/
void put(DISPID id, const variant_t& a1, const variant_t& val)
{
VARIANT vars[2]; vars[0] = val.in(); vars[1] = a1.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 2, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
/** Put property with 1 argument by name.
*/
void put(const wchar_t* name, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
put(id, a1, val);
}
/** Put property with 2 arguments by dispid.
*/
void put(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
VARIANT vars[3]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 3, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
/** Put property with 2 arguments by name.
*/
void put(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
put(id, a2, a1, val);
}
/** Put property with 3 arguments by dispid.
*/
void put(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
VARIANT vars[4]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 4, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
/** Put property with 3 arguments by name.
*/
void put(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
put(id, a3, a2, a1, val);
}
/** Put property by reference by dispid.
*/
void putref(DISPID id, const variant_t& val)
{
VARIANT vars[1]; vars[0] = val.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 1, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
/** Put property by reference by name.
*/
void putref(const wchar_t* name, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
putref(id, val);
}
void putref(DISPID id, const variant_t& a1, const variant_t& val)
{
VARIANT vars[2]; vars[0] = val.in(); vars[1] = a1.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 2, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
void putref(const wchar_t* name, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
putref(id, a1, val);
}
void putref(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
VARIANT vars[3]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 3, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
void putref(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
putref(id, a2, a1, val);
}
void putref(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
VARIANT vars[4]; vars[0] = val.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in();
DISPID did = DISPID_PROPERTYPUT;
DISPPARAMS disp = { vars, &did, 4, 1 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUTREF, &disp, 0, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
}
void putref(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& val)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
putref(id, a3, a2, a1, val);
}
/** Call method by dispid.
*/
variant_t call(DISPID id)
{
VARIANT result;
VARIANT* vars = 0;
DISPPARAMS disp = { vars, 0, 0, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
/** Call method by name.
*/
variant_t call(const wchar_t* name)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id);
}
variant_t call(DISPID id, const variant_t& a0)
{
VARIANT result;
VARIANT vars[1]; vars[0] = a0.in();
DISPPARAMS disp = { vars, 0, 1, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
variant_t call(const wchar_t* name, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id, a0);
}
variant_t call(DISPID id, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[2]; vars[0] = a0.in(); vars[1] = a1.in();
DISPPARAMS disp = { vars, 0, 2, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
variant_t call(const wchar_t* name, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id, a1, a0);
}
variant_t call(DISPID id, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[3]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in();
DISPPARAMS disp = { vars, 0, 3, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
variant_t call(const wchar_t* name, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id, a2, a1, a0);
}
variant_t call(DISPID id, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[4]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in();
DISPPARAMS disp = { vars, 0, 4, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
variant_t call(const wchar_t* name, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id, a3, a2, a1, a0);
}
variant_t call(DISPID id, const variant_t& a4, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
VARIANT result;
VARIANT vars[5]; vars[0] = a0.in(); vars[1] = a1.in(); vars[2] = a2.in(); vars[3] = a3.in(); vars[4] = a4.in();
DISPPARAMS disp = { vars, 0, 5, 0 };
HRESULT hr = raw(this)->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &result, 0, 0);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return auto_attach(result);
}
variant_t call(const wchar_t* name, const variant_t& a4, const variant_t& a3, const variant_t& a2, const variant_t& a1, const variant_t& a0)
{
DISPID id;
HRESULT hr = raw(this)->GetIDsOfNames(IID_NULL, const_cast<OLECHAR**>(&name), 1, LOCALE_USER_DEFAULT, &id);
if (FAILED(hr)) throw_com_error(raw(this), hr);
return call(id, a4, a3, a2, a1, a0);
}
};
/** \class dynamic_dispatch dispatch.h comet/dispatch.h
* Implementation of a dynamic IDispatch, allowing methods to be added to
* an IDispatch implementation.
* The class needs to be inherited from to be able to add methods.
* Each method can have up to 4 parameters.
*/
template<typename BASE> class ATL_NO_VTABLE dynamic_dispatch : public ::IDispatch {
struct method_ptr {
bool has_retval;
union {
void (BASE::*pm00)();
void (BASE::*pm01)(const variant_t&);
void (BASE::*pm02)(const variant_t&, const variant_t&);
void (BASE::*pm03)(const variant_t&, const variant_t&, const variant_t&);
void (BASE::*pm04)(const variant_t&, const variant_t&, const variant_t&, const variant_t&);
variant_t (BASE::*pm10)();
variant_t (BASE::*pm11)(const variant_t&);
variant_t (BASE::*pm12)(const variant_t&, const variant_t&);
variant_t (BASE::*pm13)(const variant_t&, const variant_t&, const variant_t&);
variant_t (BASE::*pm14)(const variant_t&, const variant_t&, const variant_t&, const variant_t&);
};
};
typedef std::map<std::wstring, DISPID> NAMEMAP;
NAMEMAP name_map_;
// Workaround VC internal compiler error
struct wrap_map_t {
std::map<unsigned, method_ptr> m;
};
typedef std::map<DISPID, wrap_map_t > MAP;
MAP map_;
void add_method(const wchar_t* name, method_ptr p, DISPID id, int type)
{
if (id == flag_value)
{
NAMEMAP::const_iterator it = name_map_.find(name);
if (it == name_map_.end())
{
id = 100000 + map_.size();
while (map_.find(id) != map_.end()) ++id;
}
else
{
id = it->second;
}
}
name_map_[name] = id;
map_[id].m[type] = p;
}
enum { flag_value = MINLONG };
public:
typedef ::IDispatch interface_is;
protected:
void remove(const wchar_t* name)
{
NAMEMAP::iterator it = name_map_.find(name);
if (it != name_map_.end()) {
DISPID id = it->second;
name_map_.erase(it);
map_.erase(id);
}
}
void add_method(const wchar_t* name, void (BASE::*pm)(), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm00 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, variant_t (BASE::*pm)(), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm10 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm11 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm12 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm13 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_METHOD ); }
void add_method(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm14 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_METHOD ); }
void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYPUT ); }
void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYPUT ); }
void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYPUT ); }
void add_put_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYPUT ); }
void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm01 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYPUTREF ); }
void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm02 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYPUTREF ); }
void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm03 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYPUTREF ); }
void add_putref_property(const wchar_t* name, void (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = false; p.pm04 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYPUTREF ); }
void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm10 = pm; add_method( name, p, id, 0 << 16 | DISPATCH_PROPERTYGET ); }
void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm11 = pm; add_method( name, p, id, 1 << 16 | DISPATCH_PROPERTYGET ); }
void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm12 = pm; add_method( name, p, id, 2 << 16 | DISPATCH_PROPERTYGET ); }
void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm13 = pm; add_method( name, p, id, 3 << 16 | DISPATCH_PROPERTYGET ); }
void add_get_property(const wchar_t* name, variant_t (BASE::*pm)(const variant_t&, const variant_t&, const variant_t&, const variant_t&), DISPID id = flag_value)
{ method_ptr p; p.has_retval = true; p.pm14 = pm; add_method( name, p, id, 4 << 16 | DISPATCH_PROPERTYGET ); }
private:
STDMETHOD(Invoke)(DISPID id, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pd, VARIANT* pVarResult, EXCEPINFO* pe, UINT* pu)
{
unsigned type = pd->cArgs << 16 | (wFlags & 15);
typename MAP::const_iterator it2 = map_.find(id);
if (it2 == map_.end()) return DISP_E_MEMBERNOTFOUND;
typename std::map<unsigned, method_ptr>::const_iterator it = it2->second.m.find(type);
if (it == it2->second.m.end()) return DISP_E_BADPARAMCOUNT;
try {
if (pd->cNamedArgs > 1) return DISP_E_NONAMEDARGS;
if (pd->cNamedArgs == 1) {
if ((wFlags & 15) != DISPATCH_PROPERTYPUT && (wFlags & 15) != DISPATCH_PROPERTYPUTREF) return DISP_E_NONAMEDARGS;
if (pd->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT) return DISP_E_NONAMEDARGS;
switch (pd->cArgs)
{
case 1:
(static_cast<BASE*>(this)->*it->second.pm01)(variant_t::create_reference(pd->rgvarg[0]));
break;
case 2:
(static_cast<BASE*>(this)->*it->second.pm02)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
case 3:
(static_cast<BASE*>(this)->*it->second.pm03)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
case 4:
(static_cast<BASE*>(this)->*it->second.pm04)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
default:
return DISP_E_MEMBERNOTFOUND;
}
}
else
{
variant_t rv;
if (it->second.has_retval)
{
switch (pd->cArgs)
{
case 0:
rv = (static_cast<BASE*>(this)->*it->second.pm10)();
break;
case 1:
rv = (static_cast<BASE*>(this)->*it->second.pm11)(variant_t::create_reference(pd->rgvarg[0]));
break;
case 2:
rv = (static_cast<BASE*>(this)->*it->second.pm12)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
case 3:
rv = (static_cast<BASE*>(this)->*it->second.pm13)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[1]));
break;
case 4:
rv = (static_cast<BASE*>(this)->*it->second.pm14)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[0]));
break;
default:
return DISP_E_MEMBERNOTFOUND;
}
}
else
{
switch (pd->cArgs)
{
case 0:
(static_cast<BASE*>(this)->*it->second.pm00)();
break;
case 1:
(static_cast<BASE*>(this)->*it->second.pm01)(variant_t::create_reference(pd->rgvarg[0]));
break;
case 2:
(static_cast<BASE*>(this)->*it->second.pm02)(variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
case 3:
(static_cast<BASE*>(this)->*it->second.pm03)(variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
case 4:
(static_cast<BASE*>(this)->*it->second.pm04)(variant_t::create_reference(pd->rgvarg[3]), variant_t::create_reference(pd->rgvarg[2]), variant_t::create_reference(pd->rgvarg[1]), variant_t::create_reference(pd->rgvarg[0]));
break;
default:
return DISP_E_MEMBERNOTFOUND;
}
}
if (pVarResult) *pVarResult = rv.detach();
}
} catch (com_error& err) {
return impl::return_com_error(err);
} catch (const std::exception& err) {
return impl::return_com_error(err);
} catch (HRESULT hr) {
return hr;
} catch (...) {
return E_FAIL;
}
return S_OK;
}
STDMETHOD(GetIDsOfNames)(REFIID, WCHAR** names, unsigned int c, LCID, DISPID* dispid)
{
bool failed = false;
for (size_t i=0; i<c; ++i)
{
NAMEMAP::const_iterator it = name_map_.find(names[i]);
if (it == name_map_.end())
{
failed = true;
dispid[i] = DISPID_UNKNOWN;
}
else
{
dispid[i] = it->second;
}
}
return failed ? DISP_E_UNKNOWNNAME : S_OK;
}
STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**)
{ return E_NOTIMPL; }
STDMETHOD(GetTypeInfoCount)(UINT *it)
{ *it = 0; return S_OK; }
};
//@}
}
#endif

View file

@ -0,0 +1,29 @@
/** \file
* Legacy header for enum-related implementations and iterators.
*
* This exists for backward compatibility only. Include specific headers
* instead.
*/
/*
* Copyright © 2000 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ENUM_H
#define COMET_ENUM_H
#include <comet/enum_common.h>
#include <comet/stl_enum.h>
#include <comet/variant_iterator.h>
#endif

View file

@ -0,0 +1,187 @@
/** \file
* Code common to enumerator implementations.
*/
/*
* Copyright © 2000 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ENUM_IMPL_H
#define COMET_ENUM_IMPL_H
#include <comet/config.h>
#include <comet/server.h>
#include <comet/stl.h>
#include <comet/variant.h>
namespace comet {
namespace impl {
template<typename T> struct type_policy;
template<> struct type_policy<VARIANT>
{
template<typename S>
static void init(VARIANT& t, const S& s)
{ ::VariantInit(&t); t = variant_t::detach( variant_t(s) ); }
static void clear(VARIANT& t) { ::VariantClear(&t); }
};
template<> struct type_policy<CONNECTDATA>
{
template<typename S>
static void init(CONNECTDATA& t, const S& s)
{
t.dwCookie = s.first;
t.pUnk =
com_ptr<IUnknown>::detach(com_ptr<IUnknown>(s.second));
}
static void clear(CONNECTDATA& t) { t.pUnk->Release(); }
};
template<
typename Itf, typename T, typename CONVERTER, typename Source>
class enumeration : public simple_object<Itf>
{
typedef type_policy<T> policy;
public:
/// \name Interface \p Itf
//@{
STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG* pceltFetched)
{
if (pceltFetched)
*pceltFetched = 0;
if (!rgelt)
return E_POINTER;
UINT i = 0;
typename Source::const_iterator backup_it_ = source_.current();
try
{
while (i < celt && source_.current() != source_.end())
{
policy::init(rgelt[i], converter_(*source_.current()));
++i;
++source_.current();
}
if (pceltFetched)
*pceltFetched = i;
}
catch (...)
{
source_.current() = backup_it_;
for (size_t j = 0; j <= i; ++j)
policy::clear(rgelt[j]);
return E_FAIL;
}
return i == celt ? S_OK : S_FALSE;
}
STDMETHOD(Reset)()
{
try
{
source_.current() = source_.begin();
}
catch (...) { return E_FAIL; }
return S_OK;
}
STDMETHOD(Skip)(ULONG celt)
{
try
{
while (celt--) source_.current()++;
}
catch (...) { return E_FAIL; }
return S_OK;
}
STDMETHOD(Clone)(Itf** ppenum)
{
try
{
enumeration* new_enum =
new enumeration(source_, converter_);
new_enum->AddRef();
*ppenum = new_enum;
}
catch (...) { return E_FAIL; }
return S_OK;
}
//@}
enumeration(
typename Source source, const CONVERTER& converter)
: source_(source), converter_(converter) {}
Source source_;
CONVERTER converter_;
private:
enumeration(const enumeration&);
enumeration& operator=(const enumeration&);
};
}
/** \struct enumerated_type_of enum.h comet/enum.h
* Traits wrapper mapping COM Enumeration interface to element.
*/
template<typename EnumItf> struct enumerated_type_of;
template<> struct enumerated_type_of<IEnumVARIANT>
{ typedef VARIANT is; };
template<> struct enumerated_type_of<IEnumConnectionPoints>
{ typedef IConnectionPoint* is; };
template<> struct enumerated_type_of<IEnumConnections>
{ typedef CONNECTDATA is; };
/** \struct ptr_converter enum.h comet/enum.h
* IUnknown Converter for containers containing Comet objects.
* \relates stl_enumeration
*/
template<typename T> struct ptr_converter : std::unary_function< com_ptr<IUnknown>, T>
{
com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x); }
};
/** \struct ptr_converter_select1st enum.h comet/enum.h
* IUnknown Converter for containers containing Comet objects as the first
* elment of a pair.
* \relates stl_enumeration
*/
template<typename T> struct ptr_converter_select1st : std::unary_function< com_ptr<IUnknown>, T>
{
com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.first); }
};
/** \struct ptr_converter_select2nd enum.h comet/enum.h
* IUnknown Converter for containers containing Comet objects as the second
* elment of a pair.
* \relates stl_enumeration
*/
template<typename T> struct ptr_converter_select2nd : std::unary_function< com_ptr<IUnknown>, T>
{
com_ptr<IUnknown> operator()(const T& x) { return impl::cast_to_unknown(x.second); }
};
}
#endif

View file

@ -0,0 +1,179 @@
/** \file
* Standard C++ iterators wrapping any COM enumerator
*/
/*
* Copyright © 2000 Sofus Mortensen
* Copyright © 2011 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ENUM_ITERATOR_H
#define COMET_ENUM_ITERATOR_H
#include <comet/config.h>
#include <comet/enum_common.h>
#include <comet/ptr.h>
#include <stdexcept>
namespace comet {
/**
* STL style iterator for COM enumerator interfaces
*/
template<typename E, typename T=enumerated_type_of<E>::is>
class enum_iterator : public std::iterator<std::input_iterator_tag, T>
{
typedef E enumerator_type;
typedef typename enumerated_type_of<E>::is element_type;
typedef impl::type_policy<element_type> policy;
com_ptr<enumerator_type> enum_;
static value_type policy_init(const element_type& element)
{
value_type out;
policy::init(out, element);
return out;
}
static value_type copy_value_from_other(const enum_iterator& other)
{
if (other.is_value_set_)
{
value_type v;
policy::init(v, other.value_);
return v;
}
else
{
return value_type();
}
}
value_type value_;
/**
* Flag that ensures the value only gets cleared if it's been set.
*
* Clearing an uninitialised value could be disastrous as it could
* contain any random bits which the clearing code could interpret as
* pointers.
*
* This could happen in the situation where the enumerator has no
* items so the value never gets set.
*/
bool is_value_set_;
public:
enum_iterator(const com_ptr<enumerator_type>& e) :
enum_(e), is_value_set_(false)
{
next();
}
enum_iterator() : is_value_set_(false) {}
enum_iterator(const enum_iterator& other) :
enum_(other.enum_), value_(copy_value_from_other(other)),
is_value_set_(other.is_value_set_) {}
enum_iterator& operator=(const enum_iterator& other)
{
enum_iterator copy(other);
swap(copy);
return *this;
}
void swap(enum_iterator& other)
{
enum_.swap(other.enum_);
std::swap(value_, other.value_);
}
/** Move to next element. */
enum_iterator& operator++()
{
next();
return *this;
}
/** Move to next element (post increment). */
enum_iterator operator++(int)
{
enum_iterator t(*this);
operator++();
return t;
}
/**
* Compare against end.
* Comparisons against a non-end iterator throw an exception.
* \todo Look into doing element comparisons.
*/
bool operator!=(const enum_iterator& other)
{
if (enum_ && other.enum_)
throw std::logic_error(
"enum_iterator comparison does not work");
return enum_ || other.enum_;
}
/** Current element. */
value_type& operator*()
{
return value_;
}
value_type* operator->()
{
return &value_;
}
private:
void next()
{
if (enum_)
{
unsigned long fetched = 0;
element_type pod;
enum_->Next(1, &pod, &fetched) | raise_exception;
if (fetched == 0)
{
enum_ = NULL;
return;
}
try
{
if (is_value_set_)
policy::clear(value_);
value_ = policy_init(pod);
is_value_set_ = true;
}
catch (...)
{
policy::clear(pod);
throw;
}
policy::clear(pod);
}
}
};
}
#endif

View file

@ -0,0 +1,429 @@
/** \file
* Provide COM Error support.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ERROR_H
#define COMET_ERROR_H
#include <comet/config.h>
#include <stdexcept>
#include <string>
#include <comet/error_fwd.h>
#include <comet/bstr.h>
#include <comet/ptr.h>
#include <comet/uuid_fwd.h>
#pragma warning(push)
#pragma warning(disable : 4290)
namespace comet {
namespace impl {
inline com_ptr<IErrorInfo> GetErrorInfo() throw()
{
IErrorInfo* ei = 0;
::GetErrorInfo(0, &ei);
return com_ptr<IErrorInfo>(auto_attach(ei));
}
inline com_ptr<ICreateErrorInfo> CreateErrorInfo() throw()
{
ICreateErrorInfo* cei = 0;
::CreateErrorInfo(&cei);
return com_ptr<ICreateErrorInfo>(auto_attach(cei));
}
template<typename Itf> inline bool supports_ErrorInfo(Itf* p)
{
com_ptr<ISupportErrorInfo> q = com_cast(com_ptr<Itf>(p));
if (q == 0) return false;
return S_OK == q->InterfaceSupportsErrorInfo(uuidof<Itf>());
}
}
/** \class com_error error.h comet/error.h
* COM error.
*/
class com_error : public std::runtime_error
{
public:
//! Construct com_error from HRESULT.
/*!
\param hr
HRESULT value of error.
*/
explicit com_error(HRESULT hr) : hr_(hr), std::runtime_error("")
{}
//! Construct com_error from HRESULT and textual description.
/*!
\param msg
Description of error.
\param hr
HRESULT value of error.
*/
explicit com_error(const bstr_t& msg, HRESULT hr = E_FAIL) : hr_(hr), std::runtime_error("")
{
com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo());
if ( !cei.is_null() ) {
try {
cei->SetDescription(msg.in());
ei_ = com_ptr<IErrorInfo>( com_cast(cei)) ;
} catch (std::bad_alloc&)
{}
}
}
//! Construct com_error from HRESULT, textual description, source, iid, help.
/*!
\param msg Description of error.
\param hr HRESULT value of error.
\param src Description of source line
\param iid Interface the error was on
\param helpFile Name of help file
\param helpContext Name of help Context
*/
explicit com_error(const bstr_t &msg, HRESULT hr, const bstr_t &src, const uuid_t &iid = uuid_t(),
const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1)
: hr_(hr), std::runtime_error("")
{
com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo());
if ( ! cei.is_null() )
{
try {
cei->SetDescription(msg.in());
if (!src.is_null() )
cei->SetSource( src.in() );
if (iid != uuid_t())
cei->SetGUID( iid );
if (!helpFile.is_null())
{
cei->SetHelpFile( helpFile.in() );
cei->SetHelpContext( helpContext );
}
ei_ = com_ptr<IErrorInfo>( com_cast(cei)) ;
} catch (std::bad_alloc&)
{}
}
}
/// Construct with an error-info and hresult.
explicit com_error(HRESULT hr, const com_ptr<IErrorInfo>& ei)
: hr_(hr), ei_(ei), std::runtime_error("")
{}
public:
//! Return a string with a description of the error
/*!
what() uses Description from IErrorInfo if such is present, otherwise FormatMessage is used
to create a description of the HRESULT error value.
\retval
A const char* string with a textual description of the error.
*/
const char* what() const throw()
{
try {
if (what_.empty()) {
what_ = s_str();
}
} catch (std::bad_alloc&) {
return 0;
}
return what_.c_str();
}
/// Returns a std::string with a description of the error.
std::string s_str() const
{
std::string ret;
get_str(ret);
return ret;
}
/// Returns a std::wstring with a description of the error.
std::wstring w_str() const
{
std::wstring ret;
get_str(ret);
return ret;
}
/// Returns a tstring with a description of the error.
tstring t_str() const
{
tstring ret;
get_str(ret);
return ret;
}
private:
void get_str(std::string& ret) const
{
if (ei_.is_null() == false)
{
bstr_t bs;
if (SUCCEEDED(ei_->GetDescription(bs.out())) && !bs.is_empty())
{
ret= bs.s_str();
return;
}
}
char* lpMsgBuf;
if (FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr_,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
reinterpret_cast<char*>(&lpMsgBuf), 0, NULL))
{
char* lpEnd = lpMsgBuf;
while (*lpEnd != '\0')
lpEnd++;
while (lpEnd > lpMsgBuf && // Trim trailing newlines
(*(lpEnd - 1) == '\n' || *(lpEnd - 1) == '\r'))
lpEnd--;
ret.assign(lpMsgBuf, lpEnd - lpMsgBuf);
LocalFree(lpMsgBuf);
}
}
void get_str(std::wstring& ret) const
{
if (ei_.is_null() == false)
{
bstr_t bs;
if (SUCCEEDED(ei_->GetDescription(bs.out())) && !bs.is_empty())
{
ret = bs.w_str();
return;
}
}
wchar_t* lpMsgBuf;
if (FormatMessageW(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr_,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
reinterpret_cast<wchar_t*>(&lpMsgBuf), 0, NULL))
{
wchar_t* lpEnd = lpMsgBuf;
while (*lpEnd != L'\0')
lpEnd++;
while (lpEnd > lpMsgBuf && // Trim trailing newlines
(*(lpEnd - 1) == L'\n' || *(lpEnd - 1) == L'\r'))
lpEnd--;
ret.assign(lpMsgBuf, lpEnd - lpMsgBuf);
LocalFree(lpMsgBuf);
}
}
public:
/** Return the HRESULT for the error.
*/
HRESULT hr() const throw()
{
return hr_;
}
/// \name wrappers for IErrorInfo
//@{
/// Description of the error.
bstr_t description() const
{
bstr_t rv;
if (!ei_.is_null()) ei_->GetDescription( rv.out() ) | raise_exception;
return rv;
}
/// The error source description.
bstr_t source() const
{
bstr_t rv;
if (!ei_.is_null()) ei_->GetSource( rv.out() ) | raise_exception;
return rv;
}
/// Interface IID.
GUID guid() const
{
GUID rv;
if (!ei_.is_null()) ei_->GetGUID( &rv ) | raise_exception;
else ZeroMemory(&rv, sizeof(rv));
return rv;
}
/// Helpfile name.
bstr_t help_file() const
{
bstr_t rv;
if (!ei_.is_null()) ei_->GetHelpFile( rv.out() ) | raise_exception;
return rv;
}
/// Help conext.
DWORD help_context() const
{
DWORD rv = 0;
if (!ei_.is_null()) ei_->GetHelpContext( &rv ) | raise_exception;
return rv;
}
//@}
/// Return the error-info object.
com_ptr<IErrorInfo> get_ei() const
{
return ei_;
}
private:
mutable std::string what_;
com_ptr<IErrorInfo> ei_;
HRESULT hr_;
};
namespace impl {
inline HRESULT return_com_error(HRESULT hr, const bstr_t &desc, const bstr_t &src = auto_attach(BSTR(NULL)),
const uuid_t &iid=CLSID_NULL, const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1)
{
com_ptr<ICreateErrorInfo> cei(impl::CreateErrorInfo());
if (cei.is_null() == false) {
try {
cei->SetDescription(desc.in());
if (!src.is_null() )
cei->SetSource( src.in() );
if (iid != uuid_t())
cei->SetGUID( iid );
if (!helpFile.is_null())
{
cei->SetHelpFile( helpFile.in() );
cei->SetHelpContext( helpContext );
}
com_ptr<IErrorInfo> ei = com_cast(cei);
::SetErrorInfo(0, ei.in());
} catch (std::bad_alloc&)
{}
}
return hr;
}
inline HRESULT return_com_error(const std::exception& err, const bstr_t &src = auto_attach(BSTR(NULL)),
const uuid_t &iid=CLSID_NULL, const bstr_t &helpFile=bstr_t(), DWORD helpContext = -1)
{
return return_com_error( E_FAIL, bstr_t(err.what()),src,iid,helpFile, helpContext );
}
inline HRESULT return_com_error(const com_error& err, const bstr_t &src = bstr_t(), const uuid_t &iid = CLSID_NULL) throw()
{
const bstr_t &cursrc =err.source();
const uuid_t &curiid =err.guid();
// Return error info with more info.
return return_com_error( err.hr(), err.description(), cursrc.is_null()?src:cursrc,
curiid.is_null()?iid:curiid, err.help_file(), err.help_context());
}
inline void throw_com_error_(HRESULT hr, const com_ptr<IErrorInfo>& ei)
{
throw_error_handler<true>::throw_error(hr, ei);
}
// Raising an HRESULT with a message
inline void raise_exception_t::operator()(const bstr_t& msg, HRESULT hr/* = E_FAIL*/) const
{
throw com_error(msg, hr);
}
// Raising an HRESULT
inline void raise_exception_t::operator()(HRESULT hr) const
{
throw com_error(hr);
}
} // namespace impl
/*! \addtogroup ErrorHandling
*/
//@{
/** Throw COM error using com_error, using HRESULT and IErrorInfo.
*/
template<typename Itf> inline void throw_com_error(Itf* p, HRESULT hr)
{
if (impl::supports_ErrorInfo(p))
{
com_ptr<IErrorInfo> ei = impl::GetErrorInfo();
if (ei.is_null() == false) impl::throw_com_error_(hr, ei);
}
throw com_error(hr);
}
template<bool OVERRIDE>
inline void throw_error_handler<OVERRIDE>::throw_error(HRESULT hr, const com_ptr<IErrorInfo> &ei)
{
throw com_error(hr, ei);
}
/**
* Construct exception for a method called on a raw COM interface.
*
* This method aims to imbue the com_error with as much information about
* the failure as possible:
* - If the interface supports IErrorInfo, the information is taken from
* the last ErrorInfo set on the current thread.
* - If not, the HRESULT alone determines the message.
*
* Use this constructor immediately after an interface returns a
* failure code before any other code can call SetErrorInfo and
* overwrite the error.
*
* \param failure_source Interface operator method returned a failure code.
* \param hr HRESULT value of error.
*
* \todo Can we add an optional user-defined message to this?
*/
template<typename Itf>
com_error com_error_from_interface(Itf* failure_source, HRESULT hr)
{
if (impl::supports_ErrorInfo(failure_source))
return com_error(hr, impl::GetErrorInfo());
else
return com_error(hr);
}
template<typename Itf>
com_error com_error_from_interface(
com_ptr<Itf> failure_source, HRESULT hr)
{
return com_error_from_interface(failure_source.get(), hr);
}
//@}
}
#pragma warning(pop)
#endif

View file

@ -0,0 +1,119 @@
/** \file
* Error forwarding - using operator|.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_ERROR_FWD_H
#define COMET_ERROR_FWD_H
#include <comet/config.h>
#include <stdexcept>
#include <wtypes.h>
#include <OAIdl.h>
#pragma warning(push)
#pragma warning(disable : 4290)
namespace comet {
template<typename Itf> class com_ptr;
class bstr_t;
class com_error;
/*! \addtogroup ErrorHandling
*/
//@{
namespace impl {
class raise_exception_t
{
public:
// Raising a std::exception
// inline void operator()(const std::exception& err) const;
// Raising an HRESULT with a message
inline void operator()(const bstr_t& msg, HRESULT hr = E_FAIL) const;
// Raising an HRESULT
inline void operator()(HRESULT hr) const;
};
}
//! Raise exception "function"
/*!
raise_exception can by used in two different ways:
First example. The 'do or die' paradigm using overloaded operator|.
Here try() is a function that returns an HRESULT. If try fails an exception will be raised.
\code
try() | raise_exception;
\endcode
Second example. Using raise_exception as an exception throwing function.
\code
raise_exception(E_POINTER);
raise_exception(L"Ran out of toilet paper!", E_FAIL);
\endcode
*/
static impl::raise_exception_t raise_exception;
//! Overload for the 'do or die' useage of raise_exception.
/*!
\code
try() | raise_exception;
\endcode
*/
namespace impl{
inline HRESULT operator|(HRESULT hr, const impl::raise_exception_t&)
{if (FAILED(hr)) raise_exception(hr); return hr; }
}
using impl::operator|;
/**! \struct throw_error_handler error_fwd.h comet\error_fwd.h
* Overridable error info handling.
* To override the error handling, use code like this, making sure
* that you define the handler before including comet/error.h.
\code
#include <comet/error_fwd.h>
template<> struct throw_error_handler<true>
{
static inline void throw_error(HRESULT hr, const com_ptr<IErrorInfo> &ei);
};
#include <comet/error.h>
// #include <mycustomerror.h>
template<>
inline void throw_error_handler<true>::throw_error(HRESULT hr, const com_ptr<IErrorInfo> &ei)
{
.... Override here ....
}
\endcode
*/
template<bool OVERRIDE>
struct throw_error_handler
{
/// Called to throw the error.
static inline void throw_error(HRESULT hr, const com_ptr<IErrorInfo> &ei);
};
//@}
}
#pragma warning(pop)
#endif

View file

@ -0,0 +1,292 @@
/** \file
* exe-server classes.
*/
/*
* Copyright © 2001, 2002 Mikael Lindgren, Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_EXE_SERVER_H
#define COMET_EXE_SERVER_H
#include <comet/server.h>
#include <comet/static_assert.h>
namespace comet {
namespace impl {
template <typename CLS_LIST> struct register_class_entry
{
typedef COMET_STRICT_TYPENAME CLS_LIST::head CLASS;
typedef COMET_STRICT_TYPENAME CLS_LIST::tail NEXT;
template <typename CLS> struct register_info
{
DWORD id;
};
static register_info<CLASS>& get_register_info()
{
static register_info<CLASS> info;
return info;
}
COMET_FORCEINLINE static HRESULT register_class_object(DWORD context, DWORD flags)
{
const IID& clsid = comtype<CLASS>::uuid();
::IUnknown* p = impl::coclass_table_entry<CLASS, false>::factory::get(clsid);
if (p)
{
HRESULT hr = ::CoRegisterClassObject(clsid, p, context, flags, &get_register_info().id);
p->Release();
if (hr != S_OK)
return hr;
}
return register_class_entry<NEXT>::register_class_object(context, flags);
}
COMET_FORCEINLINE static void revoke_class_object()
{
::CoRevokeClassObject(get_register_info().id);
register_class_entry<NEXT>::revoke_class_object();
}
};
template <> struct register_class_entry<nil>
{
COMET_FORCEINLINE static HRESULT register_class_object(DWORD context, DWORD flags)
{
COMET_NOTUSED(context);
COMET_NOTUSED(flags);
return S_OK;
}
COMET_FORCEINLINE static void revoke_class_object()
{
}
};
};
/*! \addtogroup Server
*/
//@{
//! Define an EXE server
template<typename TYPELIB, bool FREE_THREADED = false, typename TRAITS = com_server_traits<0> > class exe_server : private thread
{
#if !(_WIN32_WINNT >= 0x0400 ) && !defined(_WIN32_DCOM)
// Implementing a free threaded exe server requires NT 4.0 or better.
COMET_STATIC_ASSERT(FREE_THREADED == false);
#endif
typedef coclass_table<typename TYPELIB::coclasses, false> COCLASS_TABLE;
enum { terminate_pause = 1000, idle_shutdown_time = 5000 };
public:
exe_server(HINSTANCE instance);
exe_server(HINSTANCE instance, const GUID& appid, const tstring& appid_descr);
~exe_server();
HRESULT run();
HRESULT register_server();
HRESULT unregister_server();
HRESULT register_class_objects(DWORD context, DWORD flags);
void revoke_class_objects();
private:
event shutdown_event_;
DWORD main_thread_id_;
const GUID* appid_;
tstring appid_descr_;
virtual DWORD thread_main();
};
//@}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
exe_server<TYPELIB, FREE_THREADED, TRAITS>::exe_server(HINSTANCE instance):
main_thread_id_(::GetCurrentThreadId()),
appid_(0)
{
module_t& m = module();
m.instance(instance);
m.set_shutdown_event(shutdown_event_);
// initialize static variables in factory::get to avoid potential thread safety problem.
::IUnknown* cf = COCLASS_TABLE::find(IID_NULL);
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
exe_server<TYPELIB, FREE_THREADED, TRAITS>::exe_server(HINSTANCE instance, const GUID& appid, const tstring& appid_descr):
main_thread_id_(::GetCurrentThreadId()),
appid_(&appid), appid_descr_(appid_descr)
{
module_t& m = module();
m.instance(instance);
m.set_shutdown_event(shutdown_event_);
// initialize static variables in factory::get to avoid potential thread safety problem.
::IUnknown* cf = COCLASS_TABLE::find(IID_NULL);
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
exe_server<TYPELIB, FREE_THREADED, TRAITS>::~exe_server()
{
module().clear_shutdown_event();
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
HRESULT exe_server<TYPELIB, FREE_THREADED, TRAITS>::run()
{
thread::start();
HRESULT hr;
#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
if (FREE_THREADED)
{
hr = register_class_objects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE|REGCLS_SUSPENDED);
if (SUCCEEDED(hr))
hr = ::CoResumeClassObjects();
}
else
#endif
hr = register_class_objects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
if (SUCCEEDED(hr))
{
MSG msg;
while (::GetMessage(&msg, 0, 0, 0))
::DispatchMessage(&msg);
}
else if (thread::running())
{
shutdown_event_.set();
thread::wait(0);
}
revoke_class_objects();
Sleep(terminate_pause); //wait for any threads to finish
module().shutdown();
return hr;
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
HRESULT exe_server<TYPELIB, FREE_THREADED, TRAITS>::register_server()
{
TCHAR filename[MAX_PATH];
GetModuleFileName(module().instance(), filename, MAX_PATH);
{
HRESULT hr = impl::typelibrary_registration<TRAITS::embedded_tlb>::perform(filename, false);
if(FAILED(hr)) return SELFREG_E_TYPELIB;
}
try {
if (appid_)
{
tstring key(_T("AppID\\{") + uuid_t(*appid_).str() + _T("}"));
regkey rkey(HKEY_CLASSES_ROOT);
rkey.create(key)[_T("")] = appid_descr_;
}
COCLASS_TABLE::registration(filename, false, false, appid_);
}
catch (const com_error &e)
{
unregister_server();
return impl::return_com_error(e);
}
catch (const std::exception &e)
{
unregister_server();
::OutputDebugStringA(e.what());
return E_FAIL;
}
return S_OK;
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
HRESULT exe_server<TYPELIB, FREE_THREADED, TRAITS>::unregister_server()
{
TCHAR filename[MAX_PATH];
GetModuleFileName(module().instance(), filename, MAX_PATH);
impl::typelibrary_registration<TRAITS::embedded_tlb>::perform(filename, true);
if (appid_)
{
tstring key(_T("AppID\\{") + uuid_t(*appid_).str() + _T("}"));
regkey rkey(HKEY_CLASSES_ROOT);
rkey.delete_subkey_nothrow(key);
}
COCLASS_TABLE::registration(filename, true, false, appid_);
return S_OK;
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
HRESULT exe_server<TYPELIB, FREE_THREADED, TRAITS>::register_class_objects(DWORD context, DWORD flags)
{
return impl::register_class_entry<TYPELIB::coclasses>::register_class_object(context, flags);
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
void exe_server<TYPELIB, FREE_THREADED, TRAITS>::revoke_class_objects()
{
impl::register_class_entry<TYPELIB::coclasses>::revoke_class_object();
}
template<typename TYPELIB, bool FREE_THREADED, typename TRAITS>
DWORD exe_server<TYPELIB, FREE_THREADED, TRAITS>::thread_main()
{
module_t& m = module();
while (1)
{
shutdown_event_.wait();
do
{
m.reset_activity_flag();
} while (shutdown_event_.wait(idle_shutdown_time));
// timed out
if (!m.has_activity()) // if no activity let's really bail
{
#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM
if (FREE_THREADED)
{
::CoSuspendClassObjects();
if (!m.has_activity())
break;
}
else
break;
#else
break;
#endif
}
}
::PostThreadMessage(main_thread_id_, WM_QUIT, 0, 0);
return 0;
}
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,95 @@
/** \file
* Global Interface Table wrapper.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_GIT_H
#define COMET_GIT_H
#include <comet/config.h>
#include <comet/ptr.h>
namespace comet {
/*! \addtogroup COMType
*/
//@{
class GIT;
/// Type-safe GIT Cookie.
template<typename Itf> class GIT_cookie
{
friend class GIT;
public:
GIT_cookie(const GIT_cookie& c) : cookie_(c.cookie_) {}
explicit GIT_cookie(DWORD c) : cookie_(c) {}
GIT_cookie() : cookie_(0) {}
DWORD get_cookie() const { return cookie_; }
private:
DWORD cookie_;
};
/// Global Interface Table wrapper.
class GIT {
public:
GIT() : git_(CLSID_StdGlobalInterfaceTable)
{}
/** Register Interface in the GIT.
* \param ptr Interface to register.
* \return Type-safe cookie.
*/
template<typename Itf>
GIT_cookie<Itf> register_interface(com_ptr<Itf> const & ptr)
{
DWORD cookie;
git_->RegisterInterfaceInGlobal(ptr.get(), uuidof<Itf>(), &cookie) | raise_exception;
return GIT_cookie<Itf>(cookie);
}
/** Retrieve Interface in the GIT.
* \param c Cookie
* \return Marshalled interface.
*/
template<typename Itf>
com_ptr<Itf> get_interface(GIT_cookie<Itf> const& c)
{
Itf* itf;
git_->GetInterfaceFromGlobal(c.get_cookie(), uuidof<Itf>(), reinterpret_cast<void**>(&itf)) | raise_exception;
return auto_attach(itf);
}
/** Revoke the cookie from the GIT.
* \param c Cookie.
*/
template<typename Itf>
void revoke_interface(GIT_cookie<Itf> const& c)
{
HRESULT hr = git_->RevokeInterfaceFromGlobal(c.get_cookie());
hr;
assert(SUCCEEDED(hr));
}
private:
com_ptr< ::IGlobalInterfaceTable> git_;
};
//@}
} // namespace comet
#endif

View file

@ -0,0 +1,363 @@
/** \file
* Wrapper for Win32 API HANDLE.
*/
/*
* Copyright © 2001,2004 Sofus Mortensen, Michael Geddes
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_HANDLE_H
#define COMET_HANDLE_H
#include <comet/config.h>
#include <comet/static_assert.h>
#include <comet/error_fwd.h>
#include <comet/common.h>
#include <comet/assert.h>
#include <algorithm>
namespace comet {
/*! \addtogroup COMType
*/
//@{
/** Base and policy class for auto_handle_wrap_t type.
* This provides the destroy/detach operations for auto_handle_wrap_t as well as
* providing a base class to contain the handle and to add functions to
* that are specific to the handle type.
* \relates auto_handle_wrap_t
* \sa auto_handle_wrap_t
*/
template< typename H, long INVALID_HANDLE_ >
class handle_policy_base_t
{
public:
/// Default constructor.
handle_policy_base_t() : handle_(reinterpret_cast<H>(INVALID_HANDLE_)) {}
explicit handle_policy_base_t( H handle) : handle_(handle) {}
typedef H value_type;
//! Implicit conversion to HANDLE
operator H() const throw()
{
// This function seemed not to work with returning a namespaced
// type.
return handle_;
}
static inline H invalid_handle() { return reinterpret_cast<H>(INVALID_HANDLE_) ;}
/// Is the handle valid?
bool valid() const
{
return handle_ != invalid_handle();
}
/// Detach a raw handle
H detach_handle()
{
return swap_handle(invalid_handle());
}
//! Detaches currently held handle without closing it.
static inline value_type detach( handle_policy_base_t &handle )throw()
{
return handle.detach_handle();
}
protected:
/// Destructor to prevent one of these from being created by itself.
~handle_policy_base_t()
{ }
/// Detach the contained handle to the passed in.
void detach_to(handle_policy_base_t &rhs) throw()
{
value_type handle(handle_);
handle_= invalid_handle();
rhs.handle_ = handle;
}
H get_handle() const { return handle_; }
H *get_handle_ptr() { return &handle_;}
H swap_handle(H new_handle)
{
H old = handle_;
handle_ = new_handle;
return old;
}
private:
H handle_;
};
/** \class handle_nothrow_error_policy_t handle.h comet/handle.h
* Nothrow Error policy.
* \relates auto_handle_wrap_t
*/
struct handle_nothrow_error_policy_t
{
static void on_error()
{ }
};
/** \class handle_throw_error_policy_t handle.h comet/handle.h
* Throwing Error policy.
* \relates auto_handle_wrap_t
*/
struct handle_throw_error_policy_t
{
static void on_error()
{
DWORD err = GetLastError();
raise_exception(HRESULT_FROM_WIN32(err));
}
};
/** \class auto_handle_wrap_t handle.h comet/handle.h
* Wrapper for a Win32 API/GDI HANDLE.
* Behaves similarly to an auto_ptr in that it implements single-reference,
* reference counting, with reference-transferring assignment and
* copy-construction.
*/
template<typename C_, typename H, long INVALID_HANDLE_, typename ERROR_POLICY>
class auto_handle_wrap_t : public handle_policy_base_t<H, INVALID_HANDLE_>
{
typedef typename handle_policy_base_t<H, INVALID_HANDLE_>::value_type value_type;
protected:
/// Call destroy_handle
static inline bool destroy_( value_type h)
{
return C_::destroy_handle(h);
}
/// Destroy the handle passed in.
/** Must be implemented by the parent class.
*/
static bool destroy_handle(value_type h);
typedef handle_policy_base_t<H, INVALID_HANDLE_> policy_base ;
void set_handle( value_type h ) throw()
{
destroy_(this->swap_handle( h));
}
static bool expect_nonzero( BOOL value)
{
bool is_ok = (value != FALSE);
if (!is_ok)
ERROR_POLICY::on_error();
return is_ok;
}
public:
/// default constructor.
auto_handle_wrap_t() throw()
{}
/// A reference to a handle.
typedef const C_ &ref;
/** Assign by auto_attach.
*/
auto_handle_wrap_t( const impl::auto_attach_t<typename policy_base::value_type> &handle ) throw()
: policy_base(handle.get())
{}
/** Non-const copy constructor - takes control of the reference.
* \param rhs Handle to detach from.
*/
auto_handle_wrap_t( auto_handle_wrap_t &rhs) throw()
{
rhs.detach_to(*this);
}
/** Non-const copy constructor - takes control of the reference.
* \param rhs Handle to detach from.
*/
auto_handle_wrap_t( policy_base &rhs) throw()
{
rhs.detach_to(*this);
}
/** Destructor - closes the handle.
*/
~auto_handle_wrap_t() throw()
{
destroy_(get());
}
//! Assignment from similar handles.
/** Typically, there might be a different error policy.
*/
template<typename EP>
auto_handle_wrap_t<C_, H, INVALID_HANDLE_, EP> & operator=(auto_handle_wrap_t<C_, H, INVALID_HANDLE_, EP>& rhs) throw()
{
close_handle();
rhs.detach_to(*this);
return *this;
}
//! Assign by auto_attach
C_ &operator=(const impl::auto_attach_t<value_type> &handle )
{
close_handle();
set_handle(handle.get());
return *static_cast<C_ *>(this);
}
//! Closes the currently held handle (if any).
bool close() throw()
{
return destroy_(policy_base::detach(*this));
}
//! \name Accessor methods
//@{
//! Fitter method.
/*!
Used when calling a function that take a HANDLE* argument.
\code
auto_handle read_pipe, write_pipe;
CreatePipe(read_pipe.out(), write_pipe.out(), 0, 0));
\endcode
*/
typename policy_base::value_type* out() throw()
{
close_handle();
return this->get_handle_ptr();
}
typename policy_base::value_type get() const throw()
{ return this->get_handle(); }
typename policy_base::value_type in() const throw()
{ return this->get_handle(); }
typename policy_base::value_type *inout() throw()
{ return this->get_handle_ptr(); }
//@}
static inline const C_ &create_const_reference(const value_type &val)
{ return *reinterpret_cast<const C_ *>(&val); }
static inline C_ &create_reference(value_type &val)
{ return *reinterpret_cast<C_ *>(&val); }
/// Destroy a reference.
static bool destroy_reference(value_type h)
{
return true;
}
private:
//! Closes the currently held handle (if any).
inline void close_handle()
{
if (!close())
ERROR_POLICY::on_error();
}
};
namespace impl
{
/** \internal
*/
class THIS_IS_NOT_ALLOWED
{
~THIS_IS_NOT_ALLOWED() {}
};
}
/// Disallow closing of a const handle.
template< typename H, long INVALID_HANDLE_ >
inline impl::THIS_IS_NOT_ALLOWED CloseHandle(const handle_policy_base_t<H,INVALID_HANDLE_>&);
/// Make sure closing of an auto_handle_wrap_t detaches first.
/** \return true if CloseHandle was successful.
*/
template< typename H, long INVALID_HANDLE_ >
bool CloseHandle(handle_policy_base_t<H,INVALID_HANDLE_> &rhs)
{
return rhs.close();
}
/// Wrapper for HANDLE type
template< typename ERROR_POLICY = handle_nothrow_error_policy_t >
struct auto_handle_t : auto_handle_wrap_t< auto_handle_t<ERROR_POLICY>, HANDLE, 0, ERROR_POLICY >
{
typedef auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY > handle_base;
/// Default constructor.
auto_handle_t() {}
/// Copy constructor.
auto_handle_t( auto_handle_t &rhs)
: auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY >(rhs)
{}
/// Auto_attach constructor.
auto_handle_t( const impl::auto_attach_t< HANDLE > &rhs )
: auto_handle_wrap_t< auto_handle_t, HANDLE, 0, ERROR_POLICY >(rhs)
{ }
/// Default assignment.
auto_handle_t &operator=(auto_handle_t &rhs)
{
handle_base::operator=(rhs);
return *this;
}
auto_handle_t &operator=( const impl::auto_attach_t<HANDLE> &rhs)
{
handle_base::operator=(rhs);
return *this;
}
/// Destroy a handle
static bool destroy_handle( HANDLE h)
{
return ::CloseHandle(h) != FALSE;
}
};
/// Auto handle - wrapper for HANLDE.
typedef auto_handle_t<> auto_handle;
/// Auto handle - throwing wrapper for HANDLE.
typedef auto_handle_t< handle_throw_error_policy_t > auto_handle_throw;
/// Create a reference object to a handle that doesn't destroy it's contents.
template <typename T>
struct auto_reference_t : T
{
auto_reference_t( const comet::impl::auto_attach_t<typename T::value_type> &rhs ) : T(rhs)
{}
~auto_reference_t()
{
destroy_reference(this->detach_handle());
}
};
//@}
}
using comet::CloseHandle;
#endif

View file

@ -0,0 +1,363 @@
/** \file
* Handle Comet exceptions.
*/
/*
* Copyright 2003 Atex Media Command. All rights reserved.
* Copyright (C) 2013 Alexander Lamaison <alexander.lamaison@gmail.com>
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_HANDLE_EXCEPT_H
#define COMET_HANDLE_EXCEPT_H
#ifdef _SHOW_INC
#pragma message(" #Include " __FILE__)
#endif
#include <comet/error.h>
/** \page comethandleexception Custom Exception Handling
This allows the user to define how exception handling happens for a particular library.
Unfortunately due to a compiler bug in MSVC 6 (fixed in 7), some of the
functionality won't be available for that compiler (this has also limited
the customisability originally designed for).
To override the default behavior, specialise the struct
comet::comet_exception_handler<true> and implement the functions defined
in the default implementation comet::comet_exception_handler.
\code
comet {
template<>
struct comet_exception_handler<true> : comet_exception_handler<false>
{
static inline HRESULT catcher_all( const source_info_t &info)
{
throw;
}
};
}
\endcode
With a suitable compiler, the method comet::comet_exception_handler::rethrow can be
overridden to provide support for custom exceptions.
Don't try putting a try catch round a throw in \p catcher_all as the resulting destruct-twice
of the exception when using MSV6 will cause very hard to trace bugs.
*/
#ifdef COMET_DISABLE_EXCEPTION_RETHROW_CATCH
#define COMET_CATCH_CLASS_EX(funcName,iid) \
catch ( const com_error &err) { \
return comet_exception_handler<true>::catcher_com_error(err, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \
} catch ( const std::exception &err) { \
return comet_exception_handler<true>::catcher_exception(err, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \
} catch ( HRESULT hr ) { \
return comet_exception_handler<true>::catcher_hr(hr, impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \
} catch (...) { \
return comet_exception_handler<true>::catcher_all( impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \
}
#define COMET_CATCH_UNKNOWN(funcName, iid, clsname) \
catch ( const com_error &err) { \
comet_exception_handler<true>::catcher_com_error(err, source_info_t(funcName, iid, clsname)); \
} catch ( const std::exception &err) { \
comet_exception_handler<true>::catcher_exception(err, source_info_t(funcName, iid, clsname)); \
} catch ( HRESULT hr ) { \
comet_exception_handler<true>::catcher_hr(hr, source_info_t(funcName, iid, clsname)); \
} catch (...) { \
comet_exception_handler<true>::catcher_all( source_info_t(funcName, iid, clsname)); \
}
#else // COMET_DISABLE_EXCEPTION_RETHROW_CATCH
#define COMET_CATCH_CLASS_EX( funcName, iid) \
catch ( ... ) { \
return comet_exception_handler<true>::rethrow( impl::do_get_source_info_t<_B>::exec( static_cast<_B*>(this), source_info_t(funcName, iid))); \
}
#define COMET_CATCH_UNKNOWN(funcName, iid, clsname) \
catch ( ... ) { \
comet_exception_handler<true>::rethrow( source_info_t(funcName, iid, clsname)); \
}
#endif
/** Macro used in implementation wrappers to hide a bug with catching rethrown
* classes.
*/
#define COMET_CATCH_CLASS(funcName) COMET_CATCH_CLASS_EX(funcName, comtype<interface_is>::uuid())
// We define these new catch macros because the ones above don't seem to work.
// They use a mystery _B to get the class name. It may have been part of the
// old code-generation mechanism which we don't support any more.
#define COMET_CATCH_INTERFACE_BOUNDARY(funcName) \
catch ( ... ) { \
return ::comet::comet_exception_handler<true>::rethrow( \
::comet::source_info_t( \
funcName, ::comet::comtype<interface_is>::uuid())); \
}
#define COMET_CATCH_CLASS_INTERFACE_BOUNDARY(funcName, clsName) \
catch ( ... ) { \
return ::comet::comet_exception_handler<true>::rethrow( \
::comet::source_info_t( \
funcName, ::comet::comtype<interface_is>::uuid(), clsName)); \
}
namespace comet {
/*! \addtogroup ErrorHandling
*/
//@{
/// Specifies the source of an exception.
struct source_info_t
{
/// Default Constructor
source_info_t() {}
/// Constructor to fill in a few elements.
source_info_t(const bstr_t &par_function, const uuid_t &par_interface_uuid = uuid_t(), const bstr_t &par_coclass_name = bstr_t() )
: function_name(par_function), interface_uuid(par_interface_uuid), coclass_name(par_coclass_name) {}
bstr_t function_name; ///< Name of the function being called.
bstr_t coclass_name; ///< Coclass the method belongs to.
uuid_t coclass_uuid; ///< CLSID of the coclass.
uuid_t interface_uuid; ///< IID of the interface
bstr_t source_override; ///< Used to override the source description.
/** Returns the 'source' description, either 'source_overrride' or the
* concatenation of the coclass and function_name.
*/
bstr_t source() const
{
if ( !source_override.is_empty())
{
return source_override;
}
if (coclass_name.is_empty())
{
return function_name;
}
if (function_name.is_empty())
{
return coclass_name;
}
return coclass_name + L"." + function_name;
}
};
namespace impl
{
/** Redirect logging to calllog if enabled.
* Used so that if call-logging is loaded, the default action is to
* redirect the logging to the call-logger.
* \internal
*/
template<bool>
struct call_logger_redirect_
{
template<bool>
struct exe
{
static inline void log_exception(
const tstring& /*type*/, const tstring& /*desc*/,
const source_info_t& /*errorSource*/,
const source_info_t& /*callSource*/)
{ }
static inline bool can_log_exception()
{ return false; }
};
};
}
/** \struct error_logger_ handle_except.h comet/handle_except.h
* Default to NULL logger - and description of 'error logger' concept.
* Specialise to \b true to override.
*/
template<bool OVERRIDE>
struct error_logger_
{
/** Should the error be logged?
* \return Return true to allow error to be logged.
*/
static inline bool can_log_exception()
{
return impl::call_logger_redirect_<OVERRIDE>::template exe<OVERRIDE>::can_log_exception();
}
/// Called by exception handlers to provide logging for errors.
static inline void log_exception(const tstring &type, const tstring &desc, const source_info_t &errorSource ,const source_info_t &callSource )
{
impl::call_logger_redirect_<OVERRIDE>::template exe<OVERRIDE>::log_exception(type,desc,errorSource, callSource);
}
};
/** Common exception handler for comet.
* Specialize to \c true to overide the behaviour. It is usually convenient
* to inherit the comet_exception_handler<true> from
* comet_exception_handler<false>.
*/
template< bool OVERRIDE>
struct comet_exception_handler
{
#ifndef COMET_DISABLE_EXCEPTION_RETHROW_CATCH
/** Override to modify which exceptions are caught.
* Note that due to a severe bug in MSVC 6, this will not be called in that
* case.
*/
static inline HRESULT rethrow(const source_info_t &info)
{
try {
throw;
} catch ( const com_error &err)
{
return catcher_com_error( err, info);
}
catch ( const std::exception &err)
{
return catcher_exception( err, info);
}
catch ( HRESULT hr )
{
return catcher_hr( hr, info );
}
catch (...)
{
return catcher_all(info);
}
}
#endif // COMET_DISABLE_EXCEPTION_RETHROW_CATCH
/// Override to modify handling of com_error
static inline HRESULT catcher_com_error( const com_error &err,const source_info_t &info)
{
if ( error_logger_<OVERRIDE>::can_log_exception() )
{
source_info_t errorInfo;
errorInfo.interface_uuid = err.guid();
errorInfo.source_override = err.source();
error_logger_<OVERRIDE>::log_exception( _T("comet::com_error"), err.t_str(), errorInfo, info);
}
return impl::return_com_error(err, info.source(), info.interface_uuid);
}
/// Override to modify handling of std::exception
static inline HRESULT catcher_exception(const std::exception& err,const source_info_t &info)
{
if ( error_logger_<OVERRIDE>::can_log_exception() )
{
error_logger_<OVERRIDE>::log_exception( _T("std::exception"),
bstr_t(err.what()).t_str(),
source_info_t(), info);
}
return impl::return_com_error(err, info.source(), info.interface_uuid);
}
/// Override to modify handling of HRESULT
static inline HRESULT catcher_hr( HRESULT hr,const source_info_t &info)
{
return impl::return_com_error(hr, bstr_t(), info.source(), info.interface_uuid);
}
/// This can be overridden to provide handling of other exceptions.
static inline HRESULT catcher_all( const source_info_t &info)
{
COMET_NOTUSED(info);
throw;
}
};
namespace impl
{
/** Marker for using the coclass information.
* \relates handle_exception_default
*/
struct handle_exception_default_marker {};
/** Call the coclasses exception handler if it is marked.
* \relates handle_exception_default
*/
template <typename O>
struct do_get_source_info_t
{
/** Call the classes exception handler.
* \relates handle_exception_default
*/
template <bool USETHIS>
struct execute_handle
{
inline static void get_source_info(O * pThis, source_info_t &info)
{
pThis->get_source_info_( info );
}
};
/** Call the default global exception handler.
* \relates handle_exception_default
*/
template <>
struct execute_handle<false>
{
inline static void get_source_info(O *pThis, const source_info_t &info )
{
COMET_NOTUSED(pThis);
COMET_NOTUSED(info);
// return impl::do_handle_exception<nil, IFACE>(src);
}
};
/** Called by the interface wrappers to call the exception handlers.
* \relates handle_exception_default
*/
inline static source_info_t exec( O *pThis, source_info_t info)
{
// Either call the coclass exception handler, or the project default.
execute_handle<type_traits::conversion<O&, handle_exception_default_marker>::exists>::get_source_info( pThis, info);
/* ERRORS: If the conversion is ambiguous here, then there are probably two ways of
* getting to handle_exception_default_marker, usually via handle_exception_default<COCLASS>,
* which is already provided by by IProvideClassInfoImpl<COCLASS>.
*/
return info;
}
};
}
/** \struct handle_exception_default server.h comet/server.h
* Used by the exception handler to provide source information for the specified CoClass.
* Inherit from this class or IProvideClassInfoImpl to make sure that the
* coclass name is known about for custom coclasses.
*/
template<typename COCLASS>
struct handle_exception_default
: impl::handle_exception_default_marker // Required to mark the class as being able to handle exceptions with coclass information
{
void get_source_info_( source_info_t &info)
{
info.coclass_name = COCLASS::name();
info.coclass_uuid = comtype<COCLASS>::uuid();
}
};
// Handles the case where there is no coclass, and therefore no coclass name.
template<>
struct handle_exception_default<nil> : impl::handle_exception_default_marker
{
void get_source_info_( source_info_t &info)
{
COMET_NOTUSED(info);
}
};
//@}
}
#endif /* COMET_HANDLE_EXCEPT_H */

View file

@ -0,0 +1,546 @@
/** \file
* Implementation of QueryInterface.
*/
/*
* Copyright © 2000-2002 Sofus Mortensen, Michael Geddes
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_IMPQI_H
#define COMET_IMPQI_H
#include <wtypes.h>
#include <comet/config.h>
#include <comet/ptr.h>
#include <comet/typelist.h>
#include <comet/common.h>
#include <comet/type_traits.h>
#include <comet/uuid_fwd.h>
#include <comet/threading.h>
#include <comet/module.h>
namespace comet {
/*! \addtogroup Interfaces
*/
//@{
namespace impl {
/** Base class for recognising qi hook.
* \internal
*/
class qi_hook_itf_tag {};
}
class qi_hook {};
template<typename Itf> class qi_hook_itf : public impl::qi_hook_itf_tag{
public:
typedef Itf exposes;
virtual com_ptr<Itf> get_interface_ptr(const com_ptr< ::IUnknown>&) throw() = 0;
};
namespace impl {
template<typename Itf> COMET_FORCEINLINE bool is_interface_compatible(const uuid_t& iid, Itf*)
{
if (iid == uuidof<Itf>()) return true;
else return is_interface_compatible<comtype<Itf>::base>(iid, 0);
}
template<> COMET_FORCEINLINE bool is_interface_compatible< ::IUnknown >(const uuid_t&, ::IUnknown*)
{
return false;
}
template<> COMET_FORCEINLINE bool is_interface_compatible<nil>(const uuid_t&, nil*)
{
return false;
}
enum use_cast_t {uc_false=0, uc_static, uc_static_op, uc_qi_hook_itf, uc_qi_hook };
// remove enum for VC2005B2
template</*enum*/ use_cast_t>
struct find_compatibility_aux
{
template<typename T>
struct with
{
enum { is = false };
template<typename P> inline static bool qi(P *, const uuid_t& , com_ptr< ::IUnknown>& )
{
return false;
}
};
};
template<>
struct find_compatibility_aux<uc_static>
{
template<typename Itf> struct with {
template<typename T> static bool qi(T *This, const uuid_t& iid, com_ptr< ::IUnknown>& unk)
{
if (is_interface_compatible<Itf>(iid, 0))
{
unk = static_cast< ::IUnknown* >(static_cast<Itf*>(This));
return true;
}
return false;
}
};
};
template<>
struct find_compatibility_aux<uc_qi_hook_itf>
{
template<typename Itf> struct with {
template<typename T> static bool qi(T *This, const uuid_t& iid, com_ptr< ::IUnknown>& unk)
{
if (is_interface_compatible<typename Itf::exposes>(iid,0)) {
unk = static_cast<qi_hook_itf<typename Itf::exposes>*>(This)->get_interface_ptr( cast_to_unknown(This) );
return true;
}
return false;
}
};
};
template<>
struct find_compatibility_aux<uc_qi_hook>
{
template<typename Itf> struct with {
template<typename T> static bool qi(T *This, const uuid_t& iid, com_ptr< ::IUnknown>& unk)
{
if ( static_cast<Itf*>(This)->qi(This, iid, unk) )
return true;
else
return false;
}
};
};
/* template<>
struct find_compatibility_aux<uc_qi_hook_itf>
{
template<typename U>
struct with
{
static bool is( const uuid_t &iid){ return is_interface_compatible<U::exposes>(iid,0);}
template<class T>
static com_ptr< ::IUnknown> cast_from(T *This)
{
#ifndef NDEBUG
try {
#endif
return static_cast<qi_hook_itf<Itf::exposes>*>(This)->get_interface_ptr( cast_to_unknown(This) );
#ifndef NDEBUG
} catch (...) {
// get_interface_ptr is not allowed to throw. Return null pointer on failure
COMET_ASSERT(0);
return 0;
}
#endif
}
};
};
template<>
struct find_compatibility_aux<uc_qi_hook>
{
template<typename U>
struct with
{
static bool is( const uuid_t &iid){ return true; }
template<class T>
static com_ptr< ::IUnknown> cast_from(T *This)
{
Itf::
}
};
};*/
template< typename Itf>
struct use_cast_aux
{
enum { is_static = (type_traits::conversion<Itf*, ::IUnknown*>::exists) };
enum { is_static_op =(type_traits::is_cast_operator_compatible<Itf, ::IUnknown>::is)};
enum { is_qi_hook_itf = (type_traits::conversion<Itf*, qi_hook_itf_tag*>::exists) };
enum { is_qi_hook = (type_traits::conversion<Itf*, qi_hook*>::exists) };
// GCC Doesn't handle evaluation of ?: opeators in templates yet.
// enum { is = (int)( is_static ? uc_static: ( is_static_op ? uc_static_op : uc_false))
enum { is = is_static * uc_static +
is_qi_hook_itf * uc_qi_hook_itf +
is_qi_hook * uc_qi_hook +
is_static_op * uc_static_op };
};
template<typename Itf>
struct find_compatibility
{
enum { needs_cast_ = use_cast_aux<Itf>::is };
typedef find_compatibility_aux< (use_cast_t)needs_cast_ > compatible;
COMET_FORCEINLINE static bool with(const uuid_t &iid)
{ return compatible::template with<Itf>::is(iid); };
template<typename T>
COMET_FORCEINLINE static com_ptr< ::IUnknown> cast_from( T *This)
{ return compatible::template with<Itf>::cast_from(This); }
};
template<typename ITF_LIST> struct interface_finder
{
template<typename T> COMET_FORCEINLINE static bool find_interface(T* This, const uuid_t& iid, com_ptr< ::IUnknown>& rv)
{
typedef typename find_compatibility_aux< (use_cast_t)use_cast_aux< COMET_STRICT_TYPENAME ITF_LIST::head >::is >::template with<COMET_STRICT_TYPENAME ITF_LIST::head> fc;
if ( fc::qi(This, iid, rv) )
return true;
else
return interface_finder< COMET_STRICT_TYPENAME ITF_LIST::tail>::find_interface(This, iid, rv);
}
COMET_FORCEINLINE static bool find_interface_2(const uuid_t& iid)
{
if (is_interface_compatible<COMET_STRICT_TYPENAME ITF_LIST::head>(iid, 0)) return true;
return interface_finder< COMET_STRICT_TYPENAME ITF_LIST::tail>::find_interface_2(iid);
}
};
template<> struct interface_finder<nil>
{
template<typename T> COMET_FORCEINLINE static bool find_interface(T*, const uuid_t&, com_ptr< ::IUnknown>&)
{ return false; }
COMET_FORCEINLINE static bool find_interface_2(const uuid_t&)
{
return false;
}
};
/* template<> struct interface_finder<make_list<> >
{
template<typename T> COMET_FORCEINLINE static ::IUnknown* find_interface(T*, const uuid_t&)
{
return 0;
}
};*/
}
/** \struct typelibrary_loader impqi.h comet/impqi.h
* Type Library Loader.
* Allow provision for different means of loading a type-library.
* \param TL A \e Comet type-library.
*/
template<typename TL>
struct typelibrary_loader
{
//! Load the type-library.
/** Create a different template instantiation of this to load
* type-libraries from a different source (example - from a second
* resource in the dll).
*/
static inline HRESULT load( ITypeLib **pTypeLib)
{ return LoadRegTypeLib(uuidof<TL>(), TL::major_version, TL::minor_version, LANG_NEUTRAL, pTypeLib); }
};
/** \struct implement_qi impqi.h comet/impqi.h
* Implementation of QueryInterface. Inherits from all the types defined
* in \p ITF_LIST.
* \param ITF_LIST interface implementation list.
*/
template<typename ITF_LIST> class ATL_NO_VTABLE implement_qi : public typelist::inherit_all<ITF_LIST>
{
private:
// Hide qi
void qi();
public:
/** Get at the unknown for this class. Is here for compatibility when using
* implement_internal_qi via aggregateable_coclass for getting at a
* pointer from which to QueryInterface from.
*/
::IUnknown* get_unknown()const
{ return static_cast< typename ITF_LIST::head * >(const_cast<implement_qi<ITF_LIST> *>(this)); }
STDMETHOD(QueryInterface)(REFIID riid, void** ppv)
{
const uuid_t& iid = uuid_t::create_const_reference(riid);
com_ptr< ::IUnknown> p;
impl::interface_finder<ITF_LIST>::find_interface(this, iid, p);
if (!p) {
if (riid != IID_IUnknown) {
*ppv = 0;
return E_NOINTERFACE;
}
p = get_unknown();
// p = static_cast< ::IUnknown* >(static_cast< typename ITF_LIST::head * >(this));
}
*ppv = reinterpret_cast<void*>(p.detach());
return S_OK;
}
};
/** \struct implement_internal_qi impqi.h comet/impqi.h
* Implementation of QueryInterfaceInternal. Inherits from all the types defined
* in \p ITF_LIST. This implementation is used in aggregation.
* \param ITF_LIST interface implementation list.
*/
template<typename ITF_LIST> class ATL_NO_VTABLE implement_internal_qi : public typelist::inherit_all<ITF_LIST>
{
private:
void qi();
public:
/** Get at the unknown for this class. Is especially useful using
* aggregateable_coclass in getting at a pointer from which to
* QueryInterface from.
*/
::IUnknown* get_unknown()const
{ return static_cast< typename ITF_LIST::head * >( const_cast<implement_internal_qi<ITF_LIST> *>(this)); }
HRESULT QueryInterfaceInternal(REFIID riid, void** ppv)
{
const IID& iid = riid;
com_ptr< ::IUnknown> p;
impl::interface_finder<ITF_LIST>::find_interface(this, iid, p);
if (!p) {
if (riid != IID_IUnknown) {
*ppv = 0;
return E_NOINTERFACE;
}
// p = cast_to_unknown(this);
p = static_cast< ::IUnknown* >(static_cast<typename ITF_LIST::head*>(this));
}
*ppv = reinterpret_cast<void*>(p.detach());
return S_OK;
}
};
namespace impl {
template<typename ITF_LIST> ::IUnknown* cast_to_unknown(implement_qi<ITF_LIST>* iq)
{ return static_cast< typename ITF_LIST::head*>(iq); }
}
/** \class impl_dispatch impqi.h comet/impqi.h
* Implement IDispatch via type-library.
*/
template<typename BASE, typename TL> class ATL_NO_VTABLE impl_dispatch : public BASE
{
protected:
/// \name IDispatch Interface
//@{
STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo** ti)
{
*ti = get_ti();
if (*ti)
{
(*ti)->AddRef();
return S_OK;
}
return E_NOTIMPL;
}
STDMETHOD(GetTypeInfoCount)(UINT *it)
{ *it = 1; return S_OK; }
STDMETHOD(GetIDsOfNames)(REFIID, OLECHAR** pNames, UINT cNames, LCID, DISPID* pdispids)
{
ITypeInfo* ti = get_ti();
if (ti)
return ti->GetIDsOfNames(pNames, cNames, pdispids);
else
return E_NOTIMPL;
}
STDMETHOD(Invoke)(DISPID id, REFIID, LCID, WORD wFlags, DISPPARAMS *pd, VARIANT* pVarResult, EXCEPINFO* pe, UINT* pu)
{
ITypeInfo* ti = get_ti();
if (ti)
{
void* pThis = static_cast<BASE*>(this);
return ti->Invoke(pThis, id, wFlags, pd, pVarResult, pe, pu);
}
else
return E_NOTIMPL;
}
//@}
private:
ITypeInfo* get_ti()
{
static ITypeInfo* ti_;
if (ti_ == 0)
{
auto_cs lock(module().cs());
if (ti_ == 0)
{
com_ptr<ITypeLib> ptl;
typelibrary_loader<TL>::load(ptl.out());
if (ptl) ptl->GetTypeInfoOfGuid(uuidof<BASE>(), &ti_);
if (ti_ != 0) module().add_object_to_dispose( impl::create_itf_releaser(ti_) );
}
}
return ti_;
}
// static ITypeInfo* ti_;
};
template<typename Itf> class com_ptr;
#if 0
/** \class aggregates_interface impqi.h comet/impqi.h
* Used as an implementation for an interface to Aggregate the required
* interface.
*/
template< typename Itf >
class aggregates_interface
{
public:
/** Set the inner-unknown returned from the call to CoCreateInstance.
*/
void set_aggregate(const com_ptr< ::IUnknown>& aggobj) { ag_object_ = com_cast(aggobj); }
/** Used by QueryInteface algorithms to work out the interface
* exposed by this class.
*/
typedef Itf exposes;
operator Itf*() throw()
{
com_ptr< ::IUnknown> test = ag_object_;
return ag_object_.in();
// return com_ptr<Itf>( com_cast(ag_object_) );
}
protected:
com_ptr<Itf> ag_object_;
};
#endif
/* class FTM : public qi_hook_itf<IMarshal>
{
private:
com_ptr<IMarshal> get_interface_ptr(const com_ptr< ::IUnknown>& This) throw()
{
::IUnknown* ftm = 0;
CoCreateFreeThreadedMarshaler(This.in(), &ftm);
return com_cast(ftm);
}
};*/
/** \struct FTM impqi.h comet/impqi.h
* Aggregate the Free Threaded Marshaller.
* \code
class coclass_implementation<CoMyClass>
: public coclass<CoMyClass, thread_model::Free, FTM>
{
...
};
\endcode
*/
struct FTM : public qi_hook
{
template<typename T>
bool qi(T *This, const uuid_t& iid, com_ptr< ::IUnknown>& unk)
{
if (iid != uuidof<IMarshal>()) return false;
::IUnknown* ftm = 0;
CoCreateFreeThreadedMarshaler(impl::cast_to_unknown(This), &ftm);
unk = com_ptr< ::IMarshal>( com_cast(ftm) );
return unk != 0;
}
};
/** \struct aggregates impqi.h comet/impqi.h
* Aggregate an interface.
* \code
class coclass_implementation<CoMyClass>
: public coclass<CoMyClass, thread_model::Free, aggregates<IMyInterface> >
{
coclass_implementation()
{
aggregates<IMyInterface>create_aggregate::create_aggregate(this, CLSCTX_ALL);
}
};
\endcode
\sa coclass
*/
template<typename COCLASS, COMET_LIST_TEMPLATE> class aggregates : public qi_hook
{
com_ptr< ::IUnknown> inner_;
public:
template<typename T> bool qi(T *This, const uuid_t& iid, com_ptr< ::IUnknown>& unk)
{
typedef typename make_list<COMET_LIST_ARG_1>::result TL;
if (typelist::length<TL>::value > 0) {
if (impl::interface_finder<TL>::find_interface_2(iid) == false) return false;
}
if (inner_ == 0) return false;
::IUnknown* p;
if (SUCCEEDED(inner_.raw()->QueryInterface(iid, reinterpret_cast<void**>(&p))))
{
unk = auto_attach(p);
return true;
}
return false;
}
protected:
template<typename T> void create_aggregate(T *This, DWORD dwClsContext = CLSCTX_ALL)
{ ::IUnknown* unk_this = impl::cast_to_unknown(This); inner_ = com_ptr< ::IUnknown>(uuidof<COCLASS>(), com_ptr< ::IUnknown>::create_reference(unk_this), dwClsContext); }
};
/* template<typename Itf> class aggregates_interface : public qi_hook_itf<Itf>
{
private:
com_ptr< ::IUnknown> inner_;
com_ptr<Itf> get_interface_ptr(const com_ptr< ::IUnknown>&)
{ return com_cast(inner_); }
protected:
template<typename ITF_LIST> void create_aggregate(const CLSID& clsid, implement_qi<ITF_LIST>* This, DWORD dwClsContext = CLSCTX_ALL)
{
::IUnknown* unk_this = static_cast< typename ITF_LIST::head*>(This);
inner_ = com_ptr< ::IUnknown>(clsid, com_ptr< ::IUnknown>::create_reference(unk_this), dwClsContext);
}
template<typename ITF_LIST> void create_aggregate(const wchar_t* progid, implement_qi<ITF_LIST>* This, DWORD dwClsContext = CLSCTX_ALL)
{
::IUnknown* unk_this = static_cast< typename ITF_LIST::head*>(This);
inner_ = com_ptr< ::IUnknown>(progid, com_ptr< ::IUnknown>::create_reference(unk_this), dwClsContext);
}
};*/
//@}
}
#endif

View file

@ -0,0 +1,256 @@
/** \file
* Provide comtype which supplies information about UUIDs & inheritance,
* potentially from Interfaces not defined using a COMET type-library. Also
* defines specialisations for some such standard interfaces.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_INTERFACE_H
#define COMET_INTERFACE_H
#include <comet/config.h>
#include <ocidl.h>
#include <string>
#include <stdexcept>
#include <comet/typelist.h>
#include <comet/static_assert.h>
#include <comet/uuid_fwd.h>
#pragma warning(push, 4)
// NB: coclass_implementation _must_ have no data members.
// The comet framework uses the test
// sizeof coclass_implementation<T> == sizeof coclass_implementation<nil>
// in order to determine whether the user has specialized based on T or not.
// The logic here is that any real implementation will have a size that is at least
// sizeof IUnknown, because any real coclass_implementation must at least derive
// off IUnknown and have a "vtable" pointer.
/** \class coclass_implementation interface.h comet/interface.h
* Utility class to make the implementation of a coclass accessible from the
* servers. Implementations of coclasses defined in the type library should
* all be specialisations of this class if they are to be exposed by the
* comet server.
*/
template<typename T> class coclass_implementation {};
#pragma warning(pop)
namespace comet {
/** Provide a means for defining new comtype definitions.
*/
template<typename ITF, const UUID *ItfID, typename BASE = ::IUnknown> struct uuid_comtype
{
static const uuid_t& uuid() { return uuid_t::create_const_reference(*ItfID); }
typedef BASE base;
};
/** Provide access to uuid and base type of objects.
* Specializations allow access to information relevant to non-comet
* defined interfaces.
*/
template<typename T> struct comtype {
static const IID& uuid() throw() { return comtype<COMET_STRICT_TYPENAME T::interface_is>::uuid(); }
typedef typename comtype<COMET_STRICT_TYPENAME T::interface_is>::base base;
};
template<> struct comtype<nil> {
// static const IID& uuid() throw() { throw std::logic_error("interface.h:35"); return IID_NULL; }
typedef nil base;
};
template<> struct comtype< ::IUnknown >
{
static const IID& uuid() { return IID_IUnknown; }
typedef nil base;
};
template<> struct comtype<IConnectionPoint>
{
static const IID& uuid() { return IID_IConnectionPoint; }
typedef ::IUnknown base;
};
template<> struct comtype<IConnectionPointContainer>
{
static const IID& uuid() { return IID_IConnectionPointContainer; }
typedef ::IUnknown base;
};
template<> struct comtype<IEnumConnections>
{
static const IID& uuid() { return IID_IEnumConnections; }
typedef ::IUnknown base;
};
template<> struct comtype<IDispatch>
{
static const IID& uuid() { return IID_IDispatch; }
typedef ::IUnknown base;
};
template<> struct comtype<IEnumVARIANT>
{
static const IID& uuid() { return IID_IEnumVARIANT; }
typedef ::IUnknown base;
};
template<> struct comtype<ISupportErrorInfo>
{
static const IID& uuid() { return IID_ISupportErrorInfo; }
typedef ::IUnknown base;
};
template<> struct comtype<IErrorInfo>
{
static const IID& uuid() { return IID_IErrorInfo; }
typedef ::IUnknown base;
};
template<> struct comtype<IProvideClassInfo>
{
static const IID& uuid() throw() { return IID_IProvideClassInfo; }
typedef ::IUnknown base;
};
template<> struct comtype<IPersist>
{
static const IID& uuid() throw() { return IID_IPersist; }
typedef ::IUnknown base;
};
template<> struct comtype<IPersistFile>
{
static const IID& uuid() throw() { return IID_IPersistFile; }
typedef ::IPersist base;
};
template<> struct comtype<IPersistStream>
{
static const IID& uuid() throw() { return IID_IPersistStream; }
typedef ::IPersist base;
};
template<> struct comtype<IPersistStreamInit>
{
static const IID& uuid() throw() { return IID_IPersistStreamInit; }
typedef ::IPersist base;
};
template<> struct comtype<IMessageFilter>
{
static const IID& uuid() throw() { return IID_IMessageFilter; }
typedef ::IUnknown base;
};
template<> struct comtype<IProvideClassInfo2>
{
static const IID& uuid() throw() { return IID_IProvideClassInfo2; }
typedef ::IUnknown base;
};
template<> struct comtype<IMarshal>
{
static const IID& uuid() throw() { return IID_IMarshal; }
typedef ::IUnknown base;
};
template<> struct comtype<IFontDisp>
{
static const IID& uuid() throw() { return IID_IFontDisp; }
typedef ::IDispatch base;
};
template<> struct comtype<IPictureDisp>
{
static const IID& uuid() throw() { return IID_IPictureDisp; }
typedef ::IDispatch base;
};
template<> struct comtype<IGlobalInterfaceTable>
{
static const IID& uuid() throw() { return IID_IGlobalInterfaceTable; }
typedef ::IUnknown base;
};
template<> struct comtype<IClassFactory>
{
static const IID& uuid() throw() { return IID_IClassFactory; }
typedef ::IUnknown base;
};
template<> struct comtype<IStream>
{
static const IID& uuid() throw() { return IID_IStream; }
typedef ::IUnknown base;
};
template<> struct comtype<ISequentialStream>
{
static const IID& uuid() throw() { return IID_ISequentialStream; }
typedef ::IUnknown base;
};
//! C++ replacement of VC's __uuidof()
/*!
Use this function to an IID to an interface or coclass.
*/
template<typename Itf> inline const uuid_t& uuidof(Itf * = 0) throw()
{ return uuid_t::create_const_reference(comtype<Itf>::uuid()); }
namespace impl {
template<typename Itf> struct interface_lookup
{
static bool supports(const uuid_t& iid)
{
if (iid == uuidof<Itf>())
return true;
else
return interface_lookup< typename comtype<Itf>::base >::supports();
}
template<typename T> static Itf* cast(T* t)
{
return static_cast<Itf*>(t);
}
};
template<> struct interface_lookup<nil>
{
static bool supports(const uuid_t&)
{
return false;
}
};
/* template<> struct interface_lookup<make_list<> >
{
static bool supports(const uuid_t&)
{
return false;
}
};*/
}
} // namespace
#endif

View file

@ -0,0 +1,126 @@
/** \file
* Implementation of invariant_lock asserts.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen, Paul Hollingsworth
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_UTIL_H
#define COMET_UTIL_H
#include <comet/config.h>
#include <stdexcept>
#include <comet/error.h>
namespace comet {
/*! \addtogroup Misc
*/
//@{
/** Contains implementation of invariant_lock asserts.
*/
namespace invariant_lock_impl {
/** Provides base class for invariant_locks.
* \sa create_invariant_lock enforcer simple_enforcer
*/
class invariant_lock
{
protected:
invariant_lock() {}
invariant_lock(const invariant_lock& /*rhs*/) {}
};
/** A version of invariant_lock able to call any void member of a class.
* The member should provide an assertable condition that gets asserted
* on creation and destruction of the lock.
* \sa create_invariant_lock
*/
template<typename CLASS> struct enforcer : public invariant_lock
{
void (CLASS::*m_passert) () const;
const CLASS *m_pobj;
enforcer(const CLASS *pobj, void (CLASS::*passert) () const
) : m_pobj(pobj), m_passert(passert)
{
(m_pobj->*m_passert)();
}
~enforcer()
{
(m_pobj->*m_passert)();
}
};
/** A version of invariant_lock that calls public method \b assert_valid on
* construction and destruction of the lock.
* \sa create_invariant_lock
*/
template<typename CLASS> struct simple_enforcer : public invariant_lock
{
const CLASS *m_pobj;
simple_enforcer(const CLASS *pobj) : m_pobj(pobj)
{
m_pobj->assert_valid();
}
~simple_enforcer()
{
m_pobj->assert_valid();
}
};
} // namespace invariant_lock_impl
/*! Create an invariant_lock.
* \param pobj The class with the invariant assert
* \param assert_member The void member to call on construct & destruct
* \author Paul Hollingsworth (Paul@PaulHollingsworth.com)
* \relates invariant_lock_impl::invariant_lock
* \sa enforcer
*/
template<typename CLASS>
invariant_lock_impl::enforcer<CLASS> create_invariant_lock(const CLASS *pobj, void (CLASS::*assert_member) () const)
{
return invariant_lock_impl::enforcer<CLASS>(pobj, assert_member);
}
/*! Create a simple invariant lock.
* This lock will expect assert_valid to be publicly defined on the object
* provided.
* \param pobj The class with the invariant assert.
* \relates invariant_lock_impl::invariant_lock
* \sa simple_enforcer
* \author Paul Hollingsworth (Paul@PaulHollingsworth.com)
*/
template<typename CLASS>
invariant_lock_impl::simple_enforcer<CLASS> create_invariant_lock(const CLASS *pobj)
{
return pobj;
}
/*! Pointer class to an invariant_lock.
* Assigning a temporary to a const reference will cause the object to be
* kept for the scope of the const reference.
* \relates invariant_lock_impl::invariant_lock
* \sa create_invariant_lock
* \author Paul Hollingsworth (Paul@PaulHollingsworth.com)
*/
typedef invariant_lock_impl::invariant_lock &invariant_lock;
//@}
} // namespace
#endif

View file

@ -0,0 +1,228 @@
/** \file
* Lightweight Multiple Reader Single Writer lock.
*
* See \ref cometlwlock.
*
* The lw_lock class is heavily based on class LightweightLock written by Brad Wilson.
* see http://www.quality.nu/dotnetguy/archive/fog0000000007.aspx
* \author Brad Wilson
* \author Sofus Mortensen
*/
// Copyright (C) 1995-2002 Brad Wilson
//
// This material is provided "as is", with absolutely no warranty
// expressed or implied. Any use is at your own risk. Permission to
// use or copy this software for any purpose is hereby granted without
// fee, provided the above notices are retained on all copies.
// Permission to modify the code and to distribute modified code is
// granted, provided the above notices are retained, and a notice that
// the code was modified is included with the above copyright notice.
//
////////////////////////////////////////////////////////////////////////
/** \page cometlwlock Lightweight Lock
This lightweight lock class was adapted from samples and ideas that
were put across the ATL mailing list. It is a non-starving, kernel-
free lock that does not order writer requests. It is optimized for
use with resources that can take multiple simultaneous reads,
particularly when writing is only an occasional task.
Multiple readers may acquire the lock without any interference with
one another. As soon as a writer requests the lock, additional
readers will spin. When the pre-writer readers have all given up
control of the lock, the writer will obtain it. After the writer
has rescinded control, the additional readers will gain access
to the locked resource.
This class is very lightweight. It does not use any kernel objects.
It is designed for rapid access to resources without requiring
code to undergo process and ring changes. Because the "spin"
method for this lock is "Sleep(0)", it is a good idea to keep
the lock only long enough for short operations; otherwise, CPU
will be wasted spinning for the lock. You can change the spin
mechanism by #define'ing COMET_LW_LOCK_SPIN before including this
header file.
VERY VERY IMPORTANT: If you have a lock open with read access and
attempt to get write access as well, you will deadlock! Always
rescind your read access before requesting write access (and,
of course, don't rely on any read information across this).
This lock works in a single process only. It cannot be used, as is,
for cross-process synchronization. To do that, you should convert
this lock to using a semaphore and mutex, or use shared memory to
avoid kernel objects.
*/
/*
* Copyright © 2002 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#include <comet/config.h>
#include <comet/assert.h>
#include <windows.h>
namespace comet {
#ifndef COMET_LW_LOCK_SPIN
#define COMET_LW_LOCK_SPIN Sleep(0)
#endif
/*! \addtogroup Misc
*/
//@{
/** Provide a lightweight lock imlementation.
* See \ref cometlwlock for more information and warnings.
* \sa auto_reader_lock auto_writer_lock
*/
class lw_lock
{
// Interface
public:
/// Constructor
lw_lock()
{
reader_count_ = 0;
writer_count_ = 0;
}
/// Destructor
~lw_lock()
{
COMET_ASSERT( reader_count_ == 0 );
COMET_ASSERT( writer_count_ == 0 );
}
/// Reader lock acquisition
void enter_reader() const
{
for (;;)
{
// If there's a writer already, spin without unnecessarily
// interlocking the CPUs
if( writer_count_ != 0 )
{
COMET_LW_LOCK_SPIN;
continue;
}
// Add to the readers list
InterlockedIncrement((long *)&reader_count_ );
// Check for writers again (we may have been pre-empted). If
// there are no writers writing or waiting, then we're done.
if( writer_count_ == 0 )
break;
// Remove from the readers list, spin, try again
InterlockedDecrement((long *)&reader_count_ );
COMET_LW_LOCK_SPIN;
}
}
/// Reader lock release
void leave_reader() const
{
InterlockedDecrement((long *)&reader_count_ );
}
/// Writer lock acquisition
void enter_writer()
{
// See if we can become the writer (expensive, because it inter-
// locks the CPUs, so writing should be an infrequent process)
while( InterlockedExchange((long *)&writer_count_, 1 ) == 1 )
{
COMET_LW_LOCK_SPIN;
}
// Now we're the writer, but there may be outstanding readers.
// Spin until there aren't any more; new readers will wait now
// that we're the writer.
while( reader_count_ != 0 )
{
COMET_LW_LOCK_SPIN;
}
}
/// Writer lock release
void leave_writer()
{
writer_count_ = 0;
}
// Implementation
private:
mutable long volatile reader_count_;
mutable long volatile writer_count_;
// Declare class non-copyable
lw_lock(const lw_lock&);
lw_lock& operator=(const lw_lock&);
};
/** \class auto_reader_lock lw_lock.h comet/lw_lock.h
* Auto-release locking class for lw_lock Read acces.
* \sa lw_lock auto_writer_lock
*/
class auto_reader_lock {
public:
explicit auto_reader_lock(const lw_lock& cs) : cs_(cs) {
cs_.enter_reader();
}
~auto_reader_lock() {
cs_.leave_reader();
}
private:
auto_reader_lock& operator=(const auto_reader_lock&);
auto_reader_lock(const auto_reader_lock&);
const lw_lock& cs_;
};
/** \class auto_writer_lock lw_lock.h comet/lw_lock.h
* Auto-release locking class for lw_lock write acces.
* \sa lw_lock auto_reader_lock
*/
class auto_writer_lock {
public:
explicit auto_writer_lock(lw_lock& cs) : cs_(cs) {
cs_.enter_writer();
}
~auto_writer_lock() {
cs_.leave_writer();
}
private:
auto_writer_lock& operator=(const auto_writer_lock&);
auto_writer_lock(const auto_writer_lock&);
lw_lock& cs_;
};
//@}
}

View file

@ -0,0 +1,274 @@
/** \file
* Main functionality for providing a COM module.
*/
/*
* Copyright © 2000-2002 Sofus Mortensen, Paul Hollingsworth, Michael Geddes, Mikael Lindgren
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_MODULE_H
#define COMET_MODULE_H
#include <vector>
#include <comet/config.h>
#include <comet/tstring.h>
#include <comet/threading.h>
namespace comet {
/*!\addtogroup Server
*/
//@{
namespace impl {
/** \internal
* 'Command' base class.
*/
struct cmd_t
{
virtual void cmd() = 0;
cmd_t() {}
private:
cmd_t(const cmd_t&);
cmd_t& operator=(const cmd_t&);
};
/** \internal
* 'Command' to delete a pointer.
*
*/
template<typename T>
struct itf_releaser_t : public cmd_t
{
void cmd() { IUnknown *p = p_; p_=NULL; p->Release(); }
itf_releaser_t(T *&p) :p_(p) { }
private:
T *&p_;
itf_releaser_t(const itf_releaser_t&);
itf_releaser_t& operator=(const itf_releaser_t&);
};
template<typename T>
cmd_t *create_itf_releaser( T *&p)
{
return new itf_releaser_t<T>(p);
}
/** 'Command' to Call object_dispose on an object.
* \internal
*/
template<typename T>
struct pointer_deleter_t : public cmd_t
{
void cmd() { T *p = p_; p_=NULL; delete p;}
pointer_deleter_t(T *&p) :p_(p) { }
private:
T *&p_;
pointer_deleter_t(const pointer_deleter_t&);
pointer_deleter_t& operator=(const pointer_deleter_t&);
};
/** 'Command' to Call object_dispose on an object.
* \internal
*/
template<typename T>
struct object_disposer_t : public cmd_t
{
void cmd() { p_->object_dispose(); }
object_disposer_t( T*p) : p_(p) {}
private:
T *p_;
object_disposer_t(const object_disposer_t &);
object_disposer_t &operator=(const object_disposer_t &);
};
}
//! Create a pointer deleter command.
/** A command to delete pointers, commonly used for shutdown.
* \code
module().add_object_to_dispose(create_pointer_deleter(new my_class_t()));
* \endcode
* \sa module_t::add_object_to_dispose
*/
template<typename T>
impl::cmd_t *create_pointer_deleter( T *&p)
{
return new impl::pointer_deleter_t<T>(p);
}
//! Create an interface releaser command.
/** A command to release COM objects, commonly used for shutdown.
* Used for singletons.
* \code
module().add_object_to_dispose(create_interface_releaser(new my_coclass()));
* \endcode
* \sa module_t::add_object_to_dispose
*/
template<typename T>
impl::cmd_t *create_interface_releaser( T *&p)
{
return new impl::itf_releaser_t<T>(p);
}
//! Create a more generic object 'disposer'.
/** Creates a Command that calls a static object_dispose(p) method.
* \code
class my_class_t
{
object_dispose( my_class_t *val)
{
val->destroy_myself();
}
};
module().add_object_to_dispose(create_object_disposer(new my_class_t()));
* \endcode
* \sa module_t::add_object_to_dispose
*/
template<typename T>
impl::cmd_t *create_object_disposer( T *p )
{
return new impl::object_disposer_t<T>(p);
}
/// COM module.
struct module_t
{
//! \name Attributes
//@{
/// Return current reference count.
long rc()
{
return rc_;
}
/// Retun the HINSTANCE of the module.
HINSTANCE instance() const
{
return instance_;
}
/// Set the hinstance of the module.
void instance(HINSTANCE h)
{
instance_ = h;
}
/// Return the module's critical_section.
/** \code
auto_cs lock( module().cs() );
\endcode
*/
const critical_section& cs() const
{
return cs_;
}
//@}
//! \name Operations
//@{
/// Add to the module locks.
void lock()
{
if (InterlockedIncrement(&rc_) == 1 && shutdown_event_ != 0)
{
auto_cs lock(cs_);
if ( shutdown_event_->is_set())
shutdown_event_->reset();
}
}
/// Decrement the module lock.
void unlock()
{
if(InterlockedDecrement(&rc_)==0)
{
activity_ = true;
if (shutdown_event_ != 0)
{
auto_cs lock(cs_);
shutdown_event_->set();
}
}
}
/// Shutdown the server.
void shutdown()
{
for (std::vector<impl::cmd_t*>::iterator it = objects_to_dispose_.begin(); it != objects_to_dispose_.end(); ++it)
{
(*it)->cmd();
delete *it;
}
objects_to_dispose_.clear();
}
/// Set an event for shutdown.
void set_shutdown_event(event& shutdown_event)
{
shutdown_event_ = &shutdown_event;
}
/// Remove the event for on shutdown.
void clear_shutdown_event()
{
shutdown_event_ = 0;
}
/// Returns if there has been activity on the module since last reset.
bool has_activity() const
{
return rc_ != 0 || activity_;
}
/// Reset the activity marker.
void reset_activity_flag()
{
activity_ = false;
}
/// Add an objet to be disposed on shutdown.
void add_object_to_dispose(impl::cmd_t* p)
{
auto_cs lock(cs_);
objects_to_dispose_.push_back(p);
}
//@}
private:
long rc_;
bool activity_;
event* shutdown_event_;
HINSTANCE instance_;
critical_section cs_;
module_t() : rc_(0), activity_(false),
shutdown_event_(0), instance_(0)
{}
std::vector<impl::cmd_t*> objects_to_dispose_;
friend module_t& module();
// declare non-copyable
module_t(const module_t&);
module_t& operator=(const module_t&);
};
//! global module object
inline module_t& module()
{
static module_t m;
return m;
}
//@}
}
#endif

View file

@ -0,0 +1,72 @@
/** \file
* comtype<> definitions for interfaces in the COM header file OLEIDL.H.
* \author Gabriel Barta
*/
/*
* Copyright © 2002 Gabriel Barta
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_OLEIDL_COMTYPES_H
#define COMET_OLEIDL_COMTYPES_H
#include <comet/interface.h>
namespace comet {
template<> struct comtype< ::IOleAdviseHolder>
: public uuid_comtype< ::IOleAdviseHolder,&IID_IOleAdviseHolder, ::IUnknown> {} ;
template<> struct comtype< ::IOleCache>
: public uuid_comtype< ::IOleCache,&IID_IOleCache, ::IUnknown> {} ;
template<> struct comtype< ::IOleCache2>
: public uuid_comtype< ::IOleCache2,&IID_IOleCache2, ::IOleCache> {} ;
template<> struct comtype< ::IOleCacheControl>
: public uuid_comtype< ::IOleCacheControl,&IID_IOleCacheControl, ::IUnknown> {} ;
template<> struct comtype< ::IParseDisplayName>
: public uuid_comtype< ::IParseDisplayName,&IID_IParseDisplayName, ::IUnknown> {} ;
template<> struct comtype< ::IOleContainer>
: public uuid_comtype< ::IOleContainer,&IID_IOleContainer, ::IParseDisplayName> {} ;
template<> struct comtype< ::IOleClientSite>
: public uuid_comtype< ::IOleClientSite,&IID_IOleClientSite, ::IUnknown> {} ;
template<> struct comtype< ::IOleObject>
: public uuid_comtype< ::IOleObject,&IID_IOleObject, ::IUnknown> {} ;
template<> struct comtype< ::IOleWindow>
: public uuid_comtype< ::IOleWindow,&IID_IOleWindow, ::IUnknown> {} ;
template<> struct comtype< ::IOleLink>
: public uuid_comtype< ::IOleLink,&IID_IOleLink, ::IUnknown> {} ;
template<> struct comtype< ::IOleItemContainer>
: public uuid_comtype< ::IOleItemContainer,&IID_IOleItemContainer, ::IOleContainer> {} ;
template<> struct comtype< ::IOleInPlaceUIWindow>
: public uuid_comtype< ::IOleInPlaceUIWindow,&IID_IOleInPlaceUIWindow, ::IOleWindow> {} ;
template<> struct comtype< ::IOleInPlaceActiveObject>
: public uuid_comtype< ::IOleInPlaceActiveObject,&IID_IOleInPlaceActiveObject, ::IOleWindow> {} ;
template<> struct comtype< ::IOleInPlaceFrame>
: public uuid_comtype< ::IOleInPlaceFrame,&IID_IOleInPlaceFrame, ::IOleInPlaceUIWindow> {} ;
template<> struct comtype< ::IOleInPlaceObject>
: public uuid_comtype< ::IOleInPlaceObject,&IID_IOleInPlaceObject, ::IOleWindow> {} ;
template<> struct comtype< ::IOleInPlaceSite>
: public uuid_comtype< ::IOleInPlaceSite,&IID_IOleInPlaceSite, ::IOleWindow> {} ;
template<> struct comtype< ::IContinue>
: public uuid_comtype< ::IContinue,&IID_IContinue, ::IUnknown> {} ;
template<> struct comtype< ::IViewObject>
: public uuid_comtype< ::IViewObject,&IID_IViewObject, ::IUnknown> {} ;
template<> struct comtype< ::IViewObject2>
: public uuid_comtype< ::IViewObject2,&IID_IViewObject2, ::IViewObject> {} ;
template<> struct comtype< ::IDropSource>
: public uuid_comtype< ::IDropSource,&IID_IDropSource, ::IUnknown> {} ;
template<> struct comtype< ::IDropTarget>
: public uuid_comtype< ::IDropTarget,&IID_IDropTarget, ::IUnknown> {} ;
template<> struct comtype< ::IEnumOLEVERB>
: public uuid_comtype< ::IEnumOLEVERB,&IID_IEnumOLEVERB, ::IUnknown> {} ;
};
#endif //COMET_OLEIDL_COMTYPES_H

1261
lib/local/CamCom/comet/ptr.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,100 @@
/** \file
* Implements a class that maintains a reference count.
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen, Paul Hollingsworth
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_REFERENCE_COUNT_H
#define COMET_REFERENCE_COUNT_H
#include <comet/config.h>
#include <algorithm>
namespace comet {
/*! \addtogroup Misc
*/
//@{
/// Simple reference counter.
class reference_count
{
public:
reference_count() : rc_(0) {};
explicit reference_count(size_t x) : rc_(reinterpret_cast<size_t*>(x)) {};
reference_count(const reference_count& x) : rc_(x.rc_) {};
enum { FLAGVALUE = 1 };
bool is_flag() const {
return reinterpret_cast<size_t>(rc_) == 1;
}
// is_null
/** Implies that the there are currently no outstanding references
* to this object.
*/
bool is_null() const {
return rc_ == 0;
}
/// Increment count.
size_t operator++() {
if (!rc_) {
rc_ = new size_t(1);
}
return ++*rc_;
}
/// Decrement count.
size_t operator--() {
if (rc_) {
if (--*rc_ == 0) {
delete rc_;
rc_ = 0;
return 0;
}
return *rc_;
}
return 0;
}
void clear() {
rc_ = 0;
}
void swap(reference_count &rhs) throw() {
std::swap(rc_, rhs.rc_);
}
reference_count& operator=(reference_count& x)
{
rc_ = x.rc_;
return *this;
}
private:
size_t* rc_;
}; // class reference_count
//@}
} // namespace comet
namespace std {
//! Specialisation of std::swap for reference_count.
template<> inline void swap(comet::reference_count &lhs, comet::reference_count &rhs) COMET_STD_SWAP_NOTHROW
{
lhs.swap(rhs);
}
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
/** \file
* Base regkey type and error-policy definition.
*/
/*
* Copyright © 2000, 2001 Paul Hollingsworth
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_REGKEY_H
#define COMET_REGKEY_H
#include <comet/config.h>
#include <comet/registry.h>
#include <comet/error.h>
namespace comet
{
/** \struct reg_error regkey.h comet/regkey.h
* Standard error policy, mainly for use by registry functions.
*/
struct reg_error
{
static void on_error(LONG errcode)
{
throw com_error(HRESULT_FROM_WIN32(errcode));
}
static void on_typemismatch()
{
throw com_error(HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE));
}
};
/** Standard type for use when dealing with registry keys.
*/
typedef registry::key<reg_error> regkey;
}
namespace std {
COMET_DECLARE_SWAP(comet::regkey)
COMET_DECLARE_SWAP(comet::regkey::info_type)
COMET_DECLARE_SWAP(comet::regkey::mapped_type)
COMET_DECLARE_SWAP(comet::regkey::values_type)
COMET_DECLARE_SWAP(comet::regkey::subkeys_type)
COMET_DECLARE_SWAP(comet::regkey::value_names_type)
COMET_DECLARE_SWAP(comet::regkey::values_type::iterator)
COMET_DECLARE_SWAP(comet::regkey::values_type::const_iterator)
COMET_DECLARE_SWAP(comet::regkey::subkeys_type::iterator)
COMET_DECLARE_SWAP(comet::regkey::value_names_type::iterator)
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,363 @@
/** \file
* Scope-guards can be used to proivde transactional integrity.
*
* scope_guard and friends are adopted from source by Andrei Alexandrescu and Petru Marginean.
*
* See the <a href="http://www.cuj.com/experts/1812/alexandr.htm?topic=experts">article</a>.
*/
/*
* Copyright © 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_SCOPE_GUARD_H
#define COMET_SCOPE_GUARD_H
#include <comet/config.h>
namespace comet {
/*! \addtogroup Misc
*/
//@{
namespace impl {
/** Base class providing dismission and safe execution primitives.
*/
class scope_guard_impl_base
{
scope_guard_impl_base& operator =(const scope_guard_impl_base&);
protected:
~scope_guard_impl_base()
{
}
scope_guard_impl_base(const scope_guard_impl_base& other) throw()
: dismissed_(other.dismissed_)
{
other.dismiss();
}
template <typename J> static void safe_execute(J& j) throw()
{
if (!j.dismissed_)
try
{
j.execute();
}
catch(...)
{
}
}
mutable bool dismissed_;
public:
scope_guard_impl_base() throw() : dismissed_(false)
{
}
void dismiss() const throw()
{
dismissed_ = true;
}
};
/** 0 parameter scope guard.
* \internal
*/
template <typename F> class scope_guard_impl_0 : public scope_guard_impl_base
{
public:
~scope_guard_impl_0() throw()
{
safe_execute(*this);
}
void execute()
{
fun_();
}
scope_guard_impl_0(F fun) : fun_(fun)
{}
private:
F fun_;
};
/** 1 parameter scope guard.
* \internal
*/
template <typename F, typename P1> class scope_guard_impl_1 : public scope_guard_impl_base
{
public:
~scope_guard_impl_1() throw()
{
safe_execute(*this);
}
void execute()
{
fun_(p1_);
}
scope_guard_impl_1(F fun, P1 p1) : fun_(fun), p1_(p1)
{}
private:
F fun_;
const P1 p1_;
};
/** 2 parameter scope guard.
* \internal
*/
template <typename F, typename P1, typename P2> class scope_guard_impl_2: public scope_guard_impl_base
{
public:
~scope_guard_impl_2() throw()
{
safe_execute(*this);
}
void execute()
{
fun_(p1_, p2_);
}
scope_guard_impl_2(F fun, P1 p1, P2 p2) : fun_(fun), p1_(p1), p2_(p2)
{}
private:
F fun_;
const P1 p1_;
const P2 p2_;
};
/** 3 parameter scope guard.
* \internal
*/
template <typename F, typename P1, typename P2, typename P3> class scope_guard_impl_3 : public scope_guard_impl_base
{
public:
~scope_guard_impl_3() throw()
{
safe_execute(*this);
}
void execute()
{
fun_(p1_, p2_, p3_);
}
scope_guard_impl_3(F fun, P1 p1, P2 p2, P3 p3) : fun_(fun), p1_(p1), p2_(p2), p3_(p3)
{}
private:
F fun_;
const P1 p1_;
const P2 p2_;
const P3 p3_;
};
/** 0 parameter object scope guard.
* \internal
*/
template <class Obj, typename MemFun> class obj_scope_guard_impl_0 : public scope_guard_impl_base
{
public:
~obj_scope_guard_impl_0() throw()
{
safe_execute(*this);
}
void execute()
{
(obj_.*memFun_)();
}
obj_scope_guard_impl_0(Obj& obj, MemFun memFun)
: obj_(obj), memFun_(memFun) {}
private:
Obj& obj_;
MemFun memFun_;
};
/** 1 parameter object scope guard.
* \internal
*/
template <class Obj, typename MemFun, typename P1> class obj_scope_guard_impl_1 : public scope_guard_impl_base
{
public:
~obj_scope_guard_impl_1() throw()
{
safe_execute(*this);
}
void execute()
{
(obj_.*memFun_)(p1_);
}
obj_scope_guard_impl_1(Obj& obj, MemFun memFun, P1 p1)
: obj_(obj), memFun_(memFun), p1_(p1) {}
private:
Obj& obj_;
MemFun memFun_;
const P1 p1_;
};
/** 2 parameter object scope guard.
* \internal
*/
template <class Obj, typename MemFun, typename P1, typename P2> class obj_scope_guard_impl_2 : public scope_guard_impl_base
{
public:
~obj_scope_guard_impl_2() throw()
{
safe_execute(*this);
}
void execute()
{
(obj_.*memFun_)(p1_, p2_);
}
obj_scope_guard_impl_2(Obj& obj, MemFun memFun, P1 p1, P2 p2)
: obj_(obj), memFun_(memFun), p1_(p1), p2_(p2) {}
private:
Obj& obj_;
MemFun memFun_;
const P1 p1_;
const P2 p2_;
};
/** Implementation to allow argument to be passed by reference.
* \internal
* \sa make_guard
*/
template <class T> class ref_holder
{
T& ref_;
public:
ref_holder(T& ref) : ref_(ref) {}
operator T& () const
{
return ref_;
}
private:
// Disable assignment - not implemented
ref_holder& operator=(const ref_holder&);
};
}
/** Allow an argument to be passed by reference.
* \code
* scope_guard guard = make_guard( fun, by_ref(long) );
* \endcode
* \relates comet::scope_guard
* \internal
*/
template <class T> inline impl::ref_holder<T> by_ref(T& t)
{
return impl::ref_holder<T>(t);
}
/** Implements a scope guard with 0 parameters.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \internal
*/
template <typename F> inline impl::scope_guard_impl_0<F> make_guard(F fun)
{
return impl::scope_guard_impl_0<F>(fun);
}
/** Implements a scope guard with 1 parameter.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \sa by_ref
* \internal
*/
template <typename F, typename P1> inline impl::scope_guard_impl_1<F, P1> make_guard(F fun, P1 p1)
{
return impl::scope_guard_impl_1<F, P1>(fun, p1);
}
/** Implements a scope guard with 2 parameters.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \sa by_ref
* \internal
*/
template <typename F, typename P1, typename P2> inline impl::scope_guard_impl_2<F, P1, P2> make_guard(F fun, P1 p1, P2 p2)
{
return impl::scope_guard_impl_2<F, P1, P2>(fun, p1, p2);
}
/** Implements a scope guard with 3 parameters.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \sa by_ref
* \internal
*/
template <typename F, typename P1, typename P2, typename P3> inline impl::scope_guard_impl_3<F, P1, P2, P3> make_guard(F fun, P1 p1, P2 p2, P3 p3)
{
return impl::scope_guard_impl_3<F, P1, P2, P3>(fun, p1, p2, p3);
}
/** Implements a scope guard with 0 parameters, calling a memeber function on an object.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
*/
template <class Obj, typename MemFun> inline impl::obj_scope_guard_impl_0<Obj, MemFun> make_obj_guard(Obj& obj, MemFun memFun)
{
return impl::obj_scope_guard_impl_0<Obj, MemFun>(obj, memFun);
}
/** Implements a scope guard with 1 parameter, calling a memeber function on an object.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \sa by_ref
* \internal
*/
template <class Obj, typename MemFun, typename P1> inline impl::obj_scope_guard_impl_1<Obj, MemFun, P1> make_obj_guard(Obj& obj, MemFun memFun, P1 p1)
{
return impl::obj_scope_guard_impl_1<Obj, MemFun, P1>(obj, memFun, p1);
}
/** Implements a scope guard with 2 parameters, calling a memeber function on an object.
* \param fun Function or \link functor comet::functor \endlink
* \relates comet::scope_guard
* \sa by_ref
* \internal
*/
template <class Obj, typename MemFun, typename P1, typename P2> inline impl::obj_scope_guard_impl_2<Obj, MemFun, P1, P2> make_obj_guard(Obj& obj, MemFun memFun, P1 p1, P2 p2)
{
return impl::obj_scope_guard_impl_2<Obj, MemFun, P1, P2>(obj, memFun, p1, p2);
}
/** Pointer to a scope guard.
* Relies on const references holding on to an assigned stack object for
* the scope of the reference.
* \sa scope_guard_impl_0 obj_scope_guard_impl_0 scope_guard_impl_1 obj_scope_guard_impl_1 scope_guard_impl_2 obj_scope_guard_impl_2
*/
typedef const impl::scope_guard_impl_base& scope_guard;
//@}
} // namespace
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,139 @@
/** \file
* _NewEnum style COM enumerator backed by a smart pointer to items.
*/
/*
* Copyright © 2010 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_SMART_ENUM_H
#define COMET_SMART_ENUM_H
#include <comet/config.h>
#include <comet/enum_common.h>
#include <comet/server.h>
namespace comet {
namespace impl {
template<typename SmartPtr>
class smart_enum_source
{
public:
typedef typename SmartPtr::element_type::const_iterator
const_iterator;
explicit smart_enum_source(SmartPtr source)
: source_(source), it_(begin()) {}
const_iterator begin()
{
return source_->begin();
}
const_iterator end()
{
return source_->end();
}
const_iterator& current()
{
return it_;
}
private:
SmartPtr source_;
const_iterator it_;
};
}
/**
* Implements _NewEnum style COM object on top of smart pointer to
* a collection.
* \param Itf Enumeration Interface.
* \param C STL Style container.
* \param T Iteration Element type
* \param CONVERTER Converts container element to \p T type. (std::identity<C::value_type>)
* \sa stl_enumeration create_enum
*/
template<
typename Itf, typename SmartPtr, typename T,
typename CONVERTER=std::identity<
COMET_STRICT_TYPENAME SmartPtr::element_type::value_type> >
class smart_enumeration :
public impl::enumeration<
Itf, T, CONVERTER, impl::smart_enum_source<SmartPtr> >
{
public:
smart_enumeration(
SmartPtr container, const CONVERTER& converter=CONVERTER())
: enumeration(
impl::smart_enum_source<SmartPtr>(container), converter) {}
private:
smart_enumeration(const smart_enumeration&);
smart_enumeration& operator=(const smart_enumeration&);
};
/**
* Smart Enumeration creation helper.
*
* Creates the enumeration with the element type specified by the
* enumerated_type_of policy. To specify the element type explicitly, use
* smart_enumeration directly.
*
* \tparam ET Enumeration Type e.g. IEnumUnknown.
* \tparam SmartPtr Smart pointer (inferred from @a container parameter).
*
* \param container Smart pointer to an STL collection
* e.g. auto_ptr<vector>.
*/
template<typename ET, typename SmartPtr>
inline com_ptr<ET> make_smart_enumeration(SmartPtr container)
{
typedef typename enumerated_type_of<ET>::is T;
typedef std::identity<
COMET_STRICT_TYPENAME SmartPtr::element_type::value_type>
CONVERTER;
return new smart_enumeration<ET, SmartPtr, T, CONVERTER>(container);
}
/**
* Smart Enumeration creation helper with custom converter.
*
* Creates the enumeration with the element type specified by the
* enumerated_type_of policy. To specify the element type explicitly, use
* smart_enumeration directly.
*
* \tparam ET Enumeration Type e.g. IEnumUnknown.
* \tparam SmartPtr Smart pointer (inferred from @a container parameter).
* \tparam CONVERTER Converter type (inferred from @a converter).
*
* \param container Smart pointer to an STL collection
* e.g. auto_ptr<vector>.
* \param converter Custom converter.
*/
template<typename ET, typename SmartPtr, typename CONVERTER>
inline com_ptr<ET> make_smart_enumeration(
SmartPtr container, const CONVERTER& converter)
{
typedef typename enumerated_type_of<ET>::is T;
return new smart_enumeration<ET, SmartPtr, T, CONVERTER>(
container, converter);
}
}
#endif

View file

@ -0,0 +1,54 @@
/** \file
Provide compile-time asserts.
See <a href="http://www.boost.org">www.boost.org</a> for most recent version including documentation.
\author John Maddock
*/
/*
* Copyright © 2000, 2001 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_STATIC_ASSERT_H
#define COMET_STATIC_ASSERT_H
#include <comet/config.h>
// (C) Copyright John Maddock 2000.
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
/*
Revision history:
02 August 2000
Initial version.
*/
namespace comet {
namespace impl {
template <bool> struct COMPILE_TIME_ASSERTION_FAILURE;
template <> struct COMPILE_TIME_ASSERTION_FAILURE<true>{};
template<int> struct ct_assert_test{};
}
}
#define COMET_STATIC_ASSERT( B ) typedef ::comet::impl::ct_assert_test<sizeof(::comet::impl::COMPILE_TIME_ASSERTION_FAILURE< ( B ) >)> comet_static_assert_typedef_
#endif

View file

@ -0,0 +1,69 @@
/** \file
Provide STL extensions.
*/
/*
* Copyright © 2001 Sofus Mortensen
* Copyright © 2013 Alexander Lamaison
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_STL_H
#define COMET_STL_H
#include <comet/config.h>
#include <functional>
// add identity, select1st, and select2nd.
#if !defined(__SGI_STL_PORT) && !defined(__MINGW32__)
namespace std {
/** \internal
*/
template<typename T> struct identity : public unary_function<T, T> {
T operator()(const T& t) { return t; }
};
/** \internal
*/
template<typename T> struct select1st : public unary_function<typename T::first_type, T> {
typename T::first_type operator()(const T& t) { return t.first; }
};
/** \internal
*/
template<typename T> struct select2nd : public unary_function<typename T::second_type, T> {
typename T::second_type operator()(const T& t) { return t.second; }
};
}
#else
#include <functional>
#endif
template<typename T> class delete_fun : public std::unary_function<T, void> {
public:
void operator()(T& x) { delete x; }
};
template<typename T> class delete2nd_fun : public std::unary_function<T, void> {
public:
void operator()(T& x) { delete x.second; }
};
template<typename T> class delete1st_fun : public std::unary_function<T, void> {
public:
void operator()(T& x) { delete x.first; }
};
#endif

View file

@ -0,0 +1,188 @@
/** \file
* Implement _NewEnum style classes and iterators.
*/
/*
* Copyright © 2000 Sofus Mortensen
*
* This material is provided "as is", with absolutely no warranty
* expressed or implied. Any use is at your own risk. Permission to
* use or copy this software for any purpose is hereby granted without
* fee, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is
* granted, provided the above notices are retained, and a notice that
* the code was modified is included with the above copyright notice.
*
* This header is part of Comet version 2.
* https://github.com/alamaison/comet
*/
#ifndef COMET_STL_ENUM_H
#define COMET_STL_ENUM_H
#include <comet/config.h>
#include <comet/enum_common.h>
#include <comet/server.h>
#include <comet/stl.h>
#include <comet/variant.h>
namespace comet {
namespace impl {
template<typename Collection, typename Outer>
class stl_enum_source
{
public:
typedef typename Collection::const_iterator const_iterator;
explicit stl_enum_source(
const Collection& container, com_ptr<Outer> outer)
: outer_(outer), container_(container), it_(begin()) {}
const_iterator begin()
{
return container_.begin();
}
const_iterator end()
{
return container_.end();
}
const_iterator& current()
{
return it_;
}
private:
// Not copy-assignable
stl_enum_source& operator=(const stl_enum_source&);
com_ptr<Outer> outer_;
const Collection& container_;
const_iterator it_;
};
}
/** \class stl_enumeration_t enum.h comet/enum.h
* Implements _NewEnum style COM object.
* \param Itf Enumeration Interface.
* \param C STL Style container.
* \param T Iteration Element type (VARIANT)
* \param CONVERTER Converts container element to \p T type. (std::identity<C::value_type>)
* \sa stl_enumeration create_enum
*/
template<
typename Itf, typename C, typename T=VARIANT,
typename CONVERTER=std::identity<COMET_STRICT_TYPENAME C::value_type>,
typename TH=::IUnknown>
class stl_enumeration_t :
public impl::enumeration<
Itf, T, CONVERTER, impl::stl_enum_source<C, TH> >
{
public:
stl_enumeration_t(
const C& container, TH* outer=0,
const CONVERTER& converter=CONVERTER())
: enumeration(
impl::stl_enum_source<C, TH>(container, outer), converter) {}
private:
stl_enumeration_t(const stl_enumeration_t&);
stl_enumeration_t& operator=(const stl_enumeration_t&);
};
/**
* STL Enumeration creation helper.
*
* Creates the enumeration with the element type specified by the
* enumerated_type_of policy. To specify the element type directly, use
* stl_enumeration_t.
*
* \param ET Enumeration Type e.g. IEnumUnknown.
*/
template<typename ET>
struct stl_enumeration
{
/** Auto-Create a _NewEnum enumerator from an STL container.
* No contained object.
* \param container STL Container.
*/
template<typename C>
static com_ptr<ET> create(const C& container)
{
typedef typename enumerated_type_of<ET>::is T;
typedef std::identity<COMET_STRICT_TYPENAME C::value_type>
CONVERTER;
return new stl_enumeration_t<ET, C, T, CONVERTER, IUnknown>(
container, 0);
}
/** Auto-Create a _NewEnum enumerator from an STL container.
* \param container STL Container.
* \param th Outer or \e this pointer.
*/
template<typename C, typename TH>
static com_ptr<ET> create(const C& container, TH* th)
{
typedef typename enumerated_type_of<ET>::is T;
typedef std::identity<COMET_STRICT_TYPENAME C::value_type>
CONVERTER;
return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(
container, th);
}
/** Auto-Create a _NewEnum enumerator from an STL container, specifying
* a converter.
* \param container STL Container.
* \param th Outer or \e this pointer.
* \param converter Converter type (convert Container element to
* iterator interface element types).
*/
template<typename C, typename TH, typename CONVERTER>
static com_ptr<ET> create(
const C& container, TH* th, const CONVERTER& converter)
{
typedef typename enumerated_type_of<ET>::is T;
return new stl_enumeration_t<ET, C, T, CONVERTER, TH>(
container, th, converter);
}
};
/*! Creates IEnumVARIANT enumeration of a STL container.
* \param container STL Container.
* \param th Outer or \e this pointer.
\code
com_ptr<IEnumVARIANT> get__NewEnum() {
return create_enum( collection_, this );
}
\endcode
* \relates stl_enumeration
*/
template<typename C, typename TH>
com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th = 0)
{
return stl_enumeration<IEnumVARIANT>::create(container, th);
}
//! Creates IEnumVARIANT enumeration of a STL container with a converter.
/*! \param container STL Container.
* \param th Outer or \e this pointer.
* \param converter Converter type (convert Container element to VARIANT)
* \sa ptr_converter ptr_converter_select1st ptr_converter_select2nd
* \relates stl_enumeration
*/
template<typename C, typename TH, typename CONVERTER>
com_ptr<IEnumVARIANT> create_enum(const C& container, TH* th, CONVERTER converter)
{
return stl_enumeration<IEnumVARIANT>::create(container, th, converter);
}
}
#endif

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more