Commit a0c000ec authored by Sylvain Berfini's avatar Sylvain Berfini 🎩

Wrapped CallStats + incall stats display

parent 69f028c1
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT> <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</CompileAsWinRT>
<CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT> <CompileAsWinRT Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</CompileAsWinRT>
<GenerateXMLDocumentationFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</GenerateXMLDocumentationFiles> <GenerateXMLDocumentationFiles Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">true</GenerateXMLDocumentationFiles>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir)../submodules\oRTP\include;$(ProjectDir)../submodules/mediastreamer2/include;$(ProjectDir)../submodules/linphone;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">$(ProjectDir)../submodules\oRTP\include;$(ProjectDir)../submodules/mediastreamer2/include;$(ProjectDir)../submodules/linphone;$(ProjectDir)../submodules/linphone/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">SyncCThrow</ExceptionHandling> <ExceptionHandling Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">SyncCThrow</ExceptionHandling>
</ClCompile> </ClCompile>
<Link> <Link>
......
...@@ -34,9 +34,7 @@ Linphone::Core::LinphoneCallLog^ Linphone::Core::LinphoneCall::GetCallLog() ...@@ -34,9 +34,7 @@ Linphone::Core::LinphoneCallLog^ Linphone::Core::LinphoneCall::GetCallLog()
Linphone::Core::LinphoneCallStats^ Linphone::Core::LinphoneCall::GetAudioStats() Linphone::Core::LinphoneCallStats^ Linphone::Core::LinphoneCall::GetAudioStats()
{ {
std::lock_guard<std::recursive_mutex> lock(g_apiLock); return (Linphone::Core::LinphoneCallStats^) Linphone::Core::Utils::CreateLinphoneCallStats((void*) linphone_call_get_audio_stats(this->call), this->call);
//TODO
return nullptr;
} }
Linphone::Core::LinphoneCallParams^ Linphone::Core::LinphoneCall::GetRemoteParams() Linphone::Core::LinphoneCallParams^ Linphone::Core::LinphoneCall::GetRemoteParams()
......
...@@ -125,6 +125,7 @@ namespace Linphone ...@@ -125,6 +125,7 @@ namespace Linphone
private: private:
friend class Linphone::Core::Utils; friend class Linphone::Core::Utils;
friend ref class Linphone::Core::LinphoneCore; friend ref class Linphone::Core::LinphoneCore;
friend ref class Linphone::Core::LinphoneCallStats;
LinphoneCall(::LinphoneCall *call); LinphoneCall(::LinphoneCall *call);
~LinphoneCall(); ~LinphoneCall();
......
#include "LinphoneCallStats.h" #include "LinphoneCallStats.h"
#include "LinphoneCall.h"
#include "Server.h" #include "Server.h"
#include "coreapi\private.h"
Linphone::Core::MediaType Linphone::Core::LinphoneCallStats::GetMediaType() Linphone::Core::MediaType Linphone::Core::LinphoneCallStats::GetMediaType()
{ {
//TODO return (Linphone::Core::MediaType) this->stats->type;
return Linphone::Core::MediaType::Audio;
} }
Linphone::Core::IceState Linphone::Core::LinphoneCallStats::GetIceState() Linphone::Core::IceState Linphone::Core::LinphoneCallStats::GetIceState()
{ {
//TODO return (Linphone::Core::IceState) this->stats->ice_state;
return Linphone::Core::IceState::Failed;
} }
float Linphone::Core::LinphoneCallStats::GetDownloadBandwidth() float Linphone::Core::LinphoneCallStats::GetDownloadBandwidth()
{ {
//TODO return this->stats->download_bandwidth;
return -1;
} }
float Linphone::Core::LinphoneCallStats::GetUploadBandwidth() float Linphone::Core::LinphoneCallStats::GetUploadBandwidth()
{ {
//TODO return this->stats->upload_bandwidth;
return -1;
} }
float Linphone::Core::LinphoneCallStats::GetSenderLossRate() float Linphone::Core::LinphoneCallStats::GetSenderLossRate()
{ {
//TODO const report_block_t *srb = NULL;
return -1;
if (!stats || !stats->sent_rtcp)
return 0.0;
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
if (stats->sent_rtcp->b_cont != NULL)
msgpullup(stats->sent_rtcp, -1);
if (rtcp_is_SR(stats->sent_rtcp))
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
else if (rtcp_is_RR(stats->sent_rtcp))
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
if (!srb)
return 0.0;
return (100.0 * report_block_get_fraction_lost(srb) / 256.0);
} }
float Linphone::Core::LinphoneCallStats::GetReceiverLossRate() float Linphone::Core::LinphoneCallStats::GetReceiverLossRate()
{ {
//TODO const report_block_t* rrb = NULL;
return -1;
if (!stats || !stats->received_rtcp)
return 0.0;
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
if (stats->received_rtcp->b_cont != NULL)
msgpullup(stats->received_rtcp, -1);
if (rtcp_is_RR(stats->received_rtcp))
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
else if (rtcp_is_SR(stats->received_rtcp))
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
if (!rrb)
return 0.0;
return (100.0 * report_block_get_fraction_lost(rrb) / 256.0);
} }
float Linphone::Core::LinphoneCallStats::GetSenderInterarrivalJitter() float Linphone::Core::LinphoneCallStats::GetSenderInterarrivalJitter()
{ {
//TODO const ::LinphoneCallParams* params;
return -1; const ::PayloadType* pt;
const report_block_t* srb = NULL;
if (!stats || !this->call || !stats->sent_rtcp)
return 0.0;
params = linphone_call_get_current_params(this->call);
if (!params)
return 0.0;
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
if (stats->sent_rtcp->b_cont != NULL)
msgpullup(stats->sent_rtcp, -1);
if (rtcp_is_SR(stats->sent_rtcp))
srb = rtcp_SR_get_report_block(stats->sent_rtcp, 0);
else if (rtcp_is_RR(stats->sent_rtcp))
srb = rtcp_RR_get_report_block(stats->sent_rtcp, 0);
if (!srb)
return 0.0;
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
pt = linphone_call_params_get_used_audio_codec(params);
else
pt = linphone_call_params_get_used_video_codec(params);
if (!pt || (pt->clock_rate == 0))
return 0.0;
return ((float)report_block_get_interarrival_jitter(srb) / (float)pt->clock_rate);
} }
float Linphone::Core::LinphoneCallStats::GetReceiverInterarrivalJitter() float Linphone::Core::LinphoneCallStats::GetReceiverInterarrivalJitter()
{ {
//TODO const ::LinphoneCallParams* params;
return -1; const ::PayloadType* pt;
const report_block_t* rrb = NULL;
if (!stats || !this->call || !stats->received_rtcp)
return 0.0;
params = linphone_call_get_current_params(this->call);
if (!params)
return 0.0;
/* Perform msgpullup() to prevent crashes in rtcp_is_SR() or rtcp_is_RR() if the RTCP packet is composed of several mblk_t structure */
if (stats->received_rtcp->b_cont != NULL)
msgpullup(stats->received_rtcp, -1);
if (rtcp_is_SR(stats->received_rtcp))
rrb = rtcp_SR_get_report_block(stats->received_rtcp, 0);
else if (rtcp_is_RR(stats->received_rtcp))
rrb = rtcp_RR_get_report_block(stats->received_rtcp, 0);
if (!rrb)
return 0.0;
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
pt = linphone_call_params_get_used_audio_codec(params);
else
pt = linphone_call_params_get_used_video_codec(params);
if (!pt || (pt->clock_rate == 0))
return 0.0;
return ((float)report_block_get_interarrival_jitter(rrb) / (float)pt->clock_rate);
} }
float Linphone::Core::LinphoneCallStats::GetRoundTripDelay() float Linphone::Core::LinphoneCallStats::GetRoundTripDelay()
{ {
//TODO return this->stats->round_trip_delay;
return -1;
} }
int64 Linphone::Core::LinphoneCallStats::GetLatePacketsCumulativeNumber() int64 Linphone::Core::LinphoneCallStats::GetLatePacketsCumulativeNumber()
{ {
//TODO rtp_stats_t rtp_stats;
return -1;
if (!stats || !this->call)
return 0;
memset(&rtp_stats, 0, sizeof(rtp_stats));
if (stats->type == LINPHONE_CALL_STATS_AUDIO)
audio_stream_get_local_rtp_stats(this->call->audiostream, &rtp_stats);
#ifdef VIDEO_ENABLED
else
video_stream_get_local_rtp_stats(this->call->videostream, &rtp_stats);
#endif
return rtp_stats.outoftime;
} }
float Linphone::Core::LinphoneCallStats::GetJitterBufferSize() float Linphone::Core::LinphoneCallStats::GetJitterBufferSize()
{ {
//TODO return this->stats->jitter_stats.jitter_buffer_size_ms;
return -1; }
float Linphone::Core::LinphoneCallStats::GetLocalLossRate()
{
return this->stats->local_loss_rate;
}
float Linphone::Core::LinphoneCallStats::GetLocalLateRate()
{
return this->stats->local_late_rate;
}
Linphone::Core::LinphoneCallStats::LinphoneCallStats(::LinphoneCallStats *call_stats, ::LinphoneCall *call) :
stats(call_stats),
call(call)
{
} }
Linphone::Core::LinphoneCallStats::~LinphoneCallStats()
{
}
#pragma once #pragma once
#include "LinphoneCore.h"
namespace Linphone namespace Linphone
{ {
namespace Core namespace Core
...@@ -53,6 +55,19 @@ namespace Linphone ...@@ -53,6 +55,19 @@ namespace Linphone
/// Gets the jitter buffer size in milliseconds. /// Gets the jitter buffer size in milliseconds.
/// </summary> /// </summary>
float GetJitterBufferSize(); float GetJitterBufferSize();
float GetLocalLossRate();
float GetLocalLateRate();
private:
friend class Linphone::Core::Utils;
friend ref class Linphone::Core::LinphoneCore;
LinphoneCallStats(::LinphoneCallStats* stats, ::LinphoneCall *call);
~LinphoneCallStats();
::LinphoneCallStats *stats;
::LinphoneCall *call;
}; };
} }
} }
\ No newline at end of file
...@@ -858,6 +858,7 @@ void Linphone::Core::LinphoneCore::TunnelAddServerAndMirror(Platform::String^ ho ...@@ -858,6 +858,7 @@ void Linphone::Core::LinphoneCore::TunnelAddServerAndMirror(Platform::String^ ho
return; return;
const char* h = Linphone::Core::Utils::pstoccs(host); const char* h = Linphone::Core::Utils::pstoccs(host);
//TODO
//LinphoneTunnelConfig* config = linphone_tunnel_config_new(); //LinphoneTunnelConfig* config = linphone_tunnel_config_new();
//linphone_tunnel_config_set_host(config, h); //linphone_tunnel_config_set_host(config, h);
//linphone_tunnel_config_set_port(config, port); //linphone_tunnel_config_set_port(config, port);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "LinphoneProxyConfig.h" #include "LinphoneProxyConfig.h"
#include "LinphoneCallLog.h" #include "LinphoneCallLog.h"
#include "LinphoneCallParams.h" #include "LinphoneCallParams.h"
#include "LinphoneCallStats.h"
#include "LpConfig.h" #include "LpConfig.h"
#include "PayloadType.h" #include "PayloadType.h"
...@@ -43,7 +44,7 @@ Platform::String^ Linphone::Core::Utils::cctops(const char* cc) ...@@ -43,7 +44,7 @@ Platform::String^ Linphone::Core::Utils::cctops(const char* cc)
return ref new Platform::String(w_char); return ref new Platform::String(w_char);
} }
void Linphone::Core::Utils::LinphoneCoreSetLogHandler(void *logfunc) void Linphone::Core::Utils::LinphoneCoreSetLogHandler(void* logfunc)
{ {
std::lock_guard<std::recursive_mutex> lock(g_apiLock); std::lock_guard<std::recursive_mutex> lock(g_apiLock);
linphone_core_set_log_handler(static_cast<OrtpLogFunc>(logfunc)); linphone_core_set_log_handler(static_cast<OrtpLogFunc>(logfunc));
...@@ -55,7 +56,7 @@ void Linphone::Core::Utils::LinphoneCoreSetLogLevel(int loglevel) ...@@ -55,7 +56,7 @@ void Linphone::Core::Utils::LinphoneCoreSetLogLevel(int loglevel)
linphone_core_set_log_level(static_cast<OrtpLogLevel>(loglevel)); linphone_core_set_log_level(static_cast<OrtpLogLevel>(loglevel));
} }
Platform::Object^ Linphone::Core::Utils::CreateLpConfig(void *config) Platform::Object^ Linphone::Core::Utils::CreateLpConfig(void* config)
{ {
return ref new Linphone::Core::LpConfig((::LpConfig *)config); return ref new Linphone::Core::LpConfig((::LpConfig *)config);
} }
...@@ -65,7 +66,7 @@ Platform::Object^ Linphone::Core::Utils::CreateLpConfig(Platform::String^ config ...@@ -65,7 +66,7 @@ Platform::Object^ Linphone::Core::Utils::CreateLpConfig(Platform::String^ config
return ref new Linphone::Core::LpConfig(configPath, factoryConfigPath); return ref new Linphone::Core::LpConfig(configPath, factoryConfigPath);
} }
Platform::Object^ Linphone::Core::Utils::CreatePayloadType(void *pt) Platform::Object^ Linphone::Core::Utils::CreatePayloadType(void* pt)
{ {
return ref new Linphone::Core::PayloadType((::PayloadType *)pt); return ref new Linphone::Core::PayloadType((::PayloadType *)pt);
} }
...@@ -80,17 +81,17 @@ Platform::Object^ Linphone::Core::Utils::CreateLinphoneAddress(void* address) ...@@ -80,17 +81,17 @@ Platform::Object^ Linphone::Core::Utils::CreateLinphoneAddress(void* address)
return ref new Linphone::Core::LinphoneAddress((::LinphoneAddress *)address); return ref new Linphone::Core::LinphoneAddress((::LinphoneAddress *)address);
} }
Platform::Object^ Linphone::Core::Utils::CreateLinphoneAddressFromUri(const char *uri) Platform::Object^ Linphone::Core::Utils::CreateLinphoneAddressFromUri(const char* uri)
{ {
return ref new Linphone::Core::LinphoneAddress(uri); return ref new Linphone::Core::LinphoneAddress(uri);
} }
Platform::Object^ Linphone::Core::Utils::CreateLinphoneAuthInfo(void *auth_info) Platform::Object^ Linphone::Core::Utils::CreateLinphoneAuthInfo(void* auth_info)
{ {
return ref new Linphone::Core::LinphoneAuthInfo((::LinphoneAuthInfo *)auth_info); return ref new Linphone::Core::LinphoneAuthInfo((::LinphoneAuthInfo *)auth_info);
} }
Platform::Object^ Linphone::Core::Utils::CreateLinphoneProxyConfig(void *proxy_config) Platform::Object^ Linphone::Core::Utils::CreateLinphoneProxyConfig(void* proxy_config)
{ {
return ref new Linphone::Core::LinphoneProxyConfig((::LinphoneProxyConfig *)proxy_config); return ref new Linphone::Core::LinphoneProxyConfig((::LinphoneProxyConfig *)proxy_config);
} }
...@@ -104,3 +105,8 @@ Platform::Object^ Linphone::Core::Utils::CreateLinphoneCallParams(void* callPara ...@@ -104,3 +105,8 @@ Platform::Object^ Linphone::Core::Utils::CreateLinphoneCallParams(void* callPara
{ {
return ref new Linphone::Core::LinphoneCallParams((::LinphoneCallParams *)callParams); return ref new Linphone::Core::LinphoneCallParams((::LinphoneCallParams *)callParams);
} }
Platform::Object^ Linphone::Core::Utils::CreateLinphoneCallStats(void* callStats, void* call)
{
return ref new Linphone::Core::LinphoneCallStats((::LinphoneCallStats *)callStats, (::LinphoneCall *)call);
}
\ No newline at end of file
...@@ -26,7 +26,7 @@ namespace Linphone ...@@ -26,7 +26,7 @@ namespace Linphone
/// Define a log handler. /// Define a log handler.
/// <param name="logfunc">The function pointer of the log handler.</param> /// <param name="logfunc">The function pointer of the log handler.</param>
/// </summary> /// </summary>
static void LinphoneCoreSetLogHandler(void *logfunc); static void LinphoneCoreSetLogHandler(void* logfunc);
/// <summary> /// <summary>
/// Define the log level. /// Define the log level.
...@@ -39,7 +39,7 @@ namespace Linphone ...@@ -39,7 +39,7 @@ namespace Linphone
/// <summary> /// <summary>
/// Creates a C++/CX LpConfig object using pointer to C structure. /// Creates a C++/CX LpConfig object using pointer to C structure.
/// </summary> /// </summary>
static Platform::Object^ CreateLpConfig(void *config); static Platform::Object^ CreateLpConfig(void* config);
/// <summary> /// <summary>
/// Creates a C++/CX LpConfig object using the path to linphonerc files. /// Creates a C++/CX LpConfig object using the path to linphonerc files.
...@@ -49,7 +49,7 @@ namespace Linphone ...@@ -49,7 +49,7 @@ namespace Linphone
/// <summary> /// <summary>
/// Creates a C++/CX PayloadType object using pointer to C structure. /// Creates a C++/CX PayloadType object using pointer to C structure.
/// </summary> /// </summary>
static Platform::Object^ CreatePayloadType(void *pt); static Platform::Object^ CreatePayloadType(void* pt);
/// <summary> /// <summary>
/// Creates a C++/CX LinphoneCall object using pointer to C structure. /// Creates a C++/CX LinphoneCall object using pointer to C structure.
...@@ -64,17 +64,17 @@ namespace Linphone ...@@ -64,17 +64,17 @@ namespace Linphone
/// <summary> /// <summary>
/// Creates a C++/CX LinphoneAddress object using an URI. /// Creates a C++/CX LinphoneAddress object using an URI.
/// </summary> /// </summary>
static Platform::Object^ CreateLinphoneAddressFromUri(const char *uri); static Platform::Object^ CreateLinphoneAddressFromUri(const char* uri);
/// <summary> /// <summary>
/// Creates a C++/CX LinphoneAuthInfo object using pointer to C structure. /// Creates a C++/CX LinphoneAuthInfo object using pointer to C structure.
/// </summary> /// </summary>
static Platform::Object^ CreateLinphoneAuthInfo(void *auth_info); static Platform::Object^ CreateLinphoneAuthInfo(void* auth_info);
/// <summary> /// <summary>
/// Creates a C++/CX LinphoneProxyConfig object using pointer to C structure. /// Creates a C++/CX LinphoneProxyConfig object using pointer to C structure.
/// </summary> /// </summary>
static Platform::Object^ CreateLinphoneProxyConfig(void *proxy_config); static Platform::Object^ CreateLinphoneProxyConfig(void* proxy_config);
/// <summary> /// <summary>
/// Creates a C++/CX LinphoneCallLog object using pointer to C structure. /// Creates a C++/CX LinphoneCallLog object using pointer to C structure.
...@@ -86,6 +86,11 @@ namespace Linphone ...@@ -86,6 +86,11 @@ namespace Linphone
/// </summary> /// </summary>
static Platform::Object^ CreateLinphoneCallParams(void* callParams); static Platform::Object^ CreateLinphoneCallParams(void* callParams);
/// <summary>
/// Creates a C++/CX LinphoneCallStats object using pointer to C structure.
/// </summary>
static Platform::Object^ CreateLinphoneCallStats(void* callStats, void* call);
private: private:
static std::string wstos(std::wstring ws); static std::string wstos(std::wstring ws);
......
...@@ -164,6 +164,7 @@ ...@@ -164,6 +164,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Assets\AppBar\clear.png" /> <Content Include="Assets\AppBar\clear.png" />
<Content Include="Assets\AppBar\stats.png" />
<Content Include="Assets\linphonerc" /> <Content Include="Assets\linphonerc" />
<Content Include="Assets\linphonerc-factory" /> <Content Include="Assets\linphonerc-factory" />
<Content Include="Assets\rootca.pem" /> <Content Include="Assets\rootca.pem" />
......
...@@ -570,6 +570,51 @@ namespace Linphone.Resources { ...@@ -570,6 +570,51 @@ namespace Linphone.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Audio codec.
/// </summary>
public static string StatAudioPayload {
get {
return ResourceManager.GetString("StatAudioPayload", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Download.
/// </summary>
public static string StatDownloadBW {
get {
return ResourceManager.GetString("StatDownloadBW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to stats.
/// </summary>
public static string Stats {
get {
return ResourceManager.GetString("Stats", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Stats.
/// </summary>
public static string StatsMenu {
get {
return ResourceManager.GetString("StatsMenu", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Upload.
/// </summary>
public static string StatUploadBW {
get {
return ResourceManager.GetString("StatUploadBW", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Transport. /// Looks up a localized string similar to Transport.
/// </summary> /// </summary>
......
...@@ -329,4 +329,19 @@ http://www.linphone.org/m/help ...@@ -329,4 +329,19 @@ http://www.linphone.org/m/help
<data name="HistoryAll" xml:space="preserve"> <data name="HistoryAll" xml:space="preserve">
<value>All</value> <value>All</value>
</data> </data>
<data name="Stats" xml:space="preserve">
<value>stats</value>
</data>
<data name="StatAudioPayload" xml:space="preserve">
<value>Audio codec</value>
</data>
<data name="StatDownloadBW" xml:space="preserve">
<value>Download</value>
</data>
<data name="StatsMenu" xml:space="preserve">
<value>Stats</value>
</data>
<data name="StatUploadBW" xml:space="preserve">
<value>Upload</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -23,18 +23,28 @@ ...@@ -23,18 +23,28 @@
<!--LayoutRoot is the root grid where all page content is placed--> <!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title--> <!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28"> <StackPanel x:Name="emptyPanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Style="{StaticResource PhoneTextNormalStyle}"/> <TextBlock Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/> <TextBlock Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel>
<StackPanel x:Name="statsPanel" Grid.Row="1" Margin="12,17,0,28" Visibility="Collapsed">
<TextBlock Text="{Binding Path=LocalizedResources.StatsMenu, Source={StaticResource LocalizedStrings}}" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="DownBw" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="UpBw" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PType" Style="{StaticResource PhoneTextNormalStyle}"/>
</StackPanel> </StackPanel>
<!--ContentPanel - place additional content here--> <!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1"> <Grid x:Name="ContentPanel" Grid.Row="2">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition>
...@@ -64,6 +74,7 @@ ...@@ -64,6 +74,7 @@
<Grid Grid.Row="3" Margin="0,25,0,0"> <Grid Grid.Row="3" Margin="0,25,0,0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition> <RowDefinition Height="*"></RowDefinition>
...@@ -148,9 +159,24 @@ ...@@ -148,9 +159,24 @@
</StackPanel> </StackPanel>
</ToggleButton> </ToggleButton>
<ToggleButton
x:Name="stats"
Grid.Row="2"
Grid.Column="0"
BorderThickness="0"
Margin="-10"
Click="stats_Click_1"
Visibility="Visible"
Background="{StaticResource PhoneChromeBrush}">
<StackPanel Orientation="Vertical">
<Image x:Name="statsImg" Source="/Assets/AppBar/stats.png" Stretch="None"/>
<TextBlock HorizontalAlignment="Center" FontSize="20" Text="{Binding Path=LocalizedResources.Stats, Source={StaticResource LocalizedStrings}}" TextWrapping="Wrap" Margin="5,0,5,10"/>
</StackPanel>
</ToggleButton>
<Grid <Grid
x:Name="numpad" x:Name="numpad"
Grid.Row="2" Grid.Row="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
Visibility="Collapsed"> Visibility="Collapsed">
<Grid.RowDefinitions> <Grid.RowDefinitions>
......
using Linphone.Core; using Linphone.Core;
using Linphone.Model; using Linphone.Model;
using Linphone.Resources;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
...@@ -129,6 +131,13 @@ namespace Linphone.Views ...@@ -129,6 +131,13 @@ namespace Linphone.Views
LinphoneManager.Instance.CallController.NotifyUnmuted(); LinphoneManager.Instance.CallController.NotifyUnmuted();
} }
private void stats_Click_1(object sender, RoutedEventArgs e)
{
bool areStatsVisible = (bool)stats.IsChecked;
emptyPanel.Visibility = areStatsVisible ? Visibility.Collapsed : Visibility.Visible;
statsPanel.Visibility = areStatsVisible ? Visibility.Visible : Visibility.Collapsed;
}
/// <summary> /// <summary>
/// Called when the mute status of the microphone changes. /// Called when the mute status of the microphone changes.
/// </summary> /// </summary>
...@@ -183,6 +192,20 @@ namespace Linphone.Views ...@@ -183,6 +192,20 @@ namespace Linphone.Views
Status.Dispatcher.BeginInvoke(delegate() Status.Dispatcher.BeginInvoke(delegate()
{ {
Status.Text = mm.ToString("00") + ":" + ss.ToString("00"); Status.Text = mm.ToString("00") + ":" + ss.ToString("00");