Wednesday, February 2, 2011

Breaking News: 1st November 2011 RAD Studio deal!

Here's something that leaked from Embarcadero's future plans:
As of 1st November 2011 Embarcadero is proud to announce the release of Embarcadero RAD Studio XE Second Edition for as low as $100,— per year developer license. We will also include some new community based free services for registered customers, the services are: ednMigrate, ednBlogger, ednHelp.

What is included in the Embarcadero RAD Studio XE Second Edition:
- Delphi XE SE
- C++ Builder XE SE
- Rad PHP XE SE
- Delphi Prism XE SE
- cross platform: Windows, Mac and Linux
- full source code for VCL, RTL
- over 200 demo applications to help you get started
- latest updates included in the license

What is ednMigrate:
ednMigrate is a new community based service available for Embarcadero registered customers that will help you migrate your code from a earlier version of Delphi for example to the latest, you don't have to worry anymore about code compatibility.
You can access ednMigrate at http://ednmigrate.embarcadero.com/ and log in using your Embarcadero customer account.

What is ednBlogger:
We know that you want to share your knowledge with other developers, therefore Embarcadero will host your blog free of charge(applicable for customers only) for any Embarcadero product.
You can access ednBlogger at http://ednblogger.embarcadero.com/ and log in using your Embarcadero customer account.

What is ednHelp:
ednHelp is a new community based service available for Embarcadero registered customers that will host questions and answers related to application development, you can ask and answer as many questions as you like, the service is free of charge for all customers.
You can access ednHelp at http://ednhelp.embarcadero.com/ and log in using your Embarcadero customer account.

We have done everything we could in order to provide you with best prices for independent developers, students, new companies and existing customers:
Here are our latest prices:
TargetPrice
Independent Developers $200,—/year
Students $100,—/year
New companies $100,—/developer first year and $150,—/year starting from 2nd year
Existing customers $150,—/year
Schools $50,—/year
If you would like to do a test drive of any of our products before purchasing you can do so by navigating to http://testdrive.embarcadero.com/ select a product to download and don't forget that you can always write us a feedback at http://testdrive.embarcadero.com/feedback/ if you care to help us improve our services.

Because Embarcadero truly cares about it's customers, as of 1st February 2012 we will hold conferences all around the world so that developers can have a taste of latest technologies or share their knowledge, this is also a good opportunity for new businesses to find partners or students and independent developers to find jobs.
OK, OK you got me, it's NOT true, unfortunately... but it would be nice if Embarcadero would do something similar not the "Starter edition" stuff... which I personally disagree with it, first because it comes without source code or debugger(ewww...) and second because the price is still pretty high for students for example.
Personal appeal to Embarcadero, let's support schools and students shall we guys?! in some schools in Romania the pascal language is STILL present, however I'm NOT sure if that will be true in 1 or 2 years from now, given the fact that Microsoft is doing a terrific job spreading it's software all around the world, I would NOT be surprised if they will have Visual Studio in most schools.

And another thing, I get more than 60% of my blog hits from searches like "Delphi distiller", "Delphi XE distiller" and similar keywords, what does THAT mean to Embarcadero?! shit load of customers and money TOTALLY WASTED, is Embarcadero that rich?! probably...

One more thing, before people will start criticise me, please DO NOT THINK that $140,— per start edition or whatever the price is or will be is NOT a lot of money, you don't take into account countries that have thousands of Delphi developers which earn ~$500,—/month or less, so yes $140,— might not be a lot for US or European citizens but for other parts of the world it is.

Tuesday, February 1, 2011

Laptop specific functions

First I would like to thank each and every one of the developers from stackoverflow who helped me out in detecting if application is running on laptop by answering my question.
I have pushed the envelop further by defining some helper functions which retrieves laptop specific information and some other as well, so without further introduction here's the unit that I've wrote, feel free to use it in commercial and/or personal applications AT YOUR OWN RISK of course, also if you find some flaws(high probability -- haven't tested enough) please feel free to drop a comment.
unit uDGMobileUtils;

interface

(*******************************************************************************

  Author:
    Dorin Duminica

  Note:
    That Parts of the code are Copyright© of Microsoft Corporation.
    All Rights Reserved.

  Disclaimer:
    Using the following code represents your acknowledgement that YOU TAKE
    FULL RESPONSABILITY of any damage it can and/or might cause to your
    system, country, pets, etc.

  Requirements:
    According to Microsoft the following code should work starting from
    Windows 2000 Professional and Server

*******************************************************************************)

uses
  Windows;

{$Z4} // required in order to have 4 byte enumerated type

type
  SYSTEM_POWER_STATE =(
    PowerSystemUnspecified,
    PowerSystemWorking,
    PowerSystemSleeping1,
    PowerSystemSleeping2,
    PowerSystemSleeping3,
    PowerSystemHibernate,
    PowerSystemShutdown,
    PowerSystemMaximum);

{$Z1} // restore enumerated type to 1 byte

const
  SYSTEM_POWER_STATE_NAMES: array[SYSTEM_POWER_STATE] of string = (
    'Unspecified',
    'Working',
    'Sleeping 1',
    'Sleeping 2',
    'Sleeping 3',
    'Hibernate',
    'Shutdown',
    'Maximum');

type
  BATTERY_REPORTING_SCALE = record
    Granularity: ULONG;
    Capacity: ULONG;
  end;

  PBATTERY_REPORTING_SCALE = ^BATTERY_REPORTING_SCALE;

type
  SYSTEM_POWER_CAPABILITIES = record
    // If this member is TRUE, there is a system power button.
    PowerButtonPresent: Boolean;
    // If this member is TRUE, there is a system sleep button.
    SleepButtonPresent: Boolean;
    // If this member is TRUE, there is a lid switch.
    LidPresent: Boolean;
    // for S1 —> S5 check microsoft site
    SystemS1: Boolean;
    SystemS2: Boolean;
    SystemS3: Boolean;
    SystemS4: Boolean;
    SystemS5: Boolean;
    // If this member is TRUE, the operating system supports power off state S5 (soft off).
    HiberFilePresent: Boolean;
    // If this member is TRUE, the system supports wake capabilities.
    FullWake: Boolean;
    // If this member is TRUE, the system supports video display dimming capabilities.
    VideoDimPresent: Boolean;
    // If this member is TRUE, the system supports APM BIOS power management features.
    ApmPresent: Boolean;
    // If this member is TRUE, there is an uninterruptible power supply (UPS).
    UpsPresent: Boolean;
    // If this member is TRUE, the system supports thermal zones.
    ThermalControl: Boolean;
    // If this member is TRUE, the system supports processor throttling.
    ProcessorThrottle: Boolean;
    // The minimum level of system processor throttling supported,
    // expressed as a percentage.
    ProcessorMinThrottle: UCHAR;
    // The maximum level of system processor throttling supported,
    // expressed as a percentage.
    ProcessorMaxThrottle: UCHAR;
    // If this member is TRUE, the system supports the hybrid sleep state.
    // Windows Server 2003 and Windows XP:  Hybrid sleep is not supported.
    // Windows 2000:  This member is not supported.
    FastSystemS4: Boolean;
    // reserved
    spare2: array [0 .. 3] of UCHAR;
    // If this member is TRUE, the system supports allowing the removal of power
    // to fixed disk devices.
    DiskSpinDown: Boolean;
    // reserved
    spare3: array [0 .. 7] of UCHAR;
    // If this member is TRUE, there are one or more batteries in the system.
    SystemBatteriesPresent: Boolean;
    // If this member is TRUE, the system batteries are short-term.
    // Short-term batteries are used in uninterruptible power supplies (UPS).
    BatteriesAreShortTerm: Boolean;
    // A BATTERY_REPORTING_SCALE structure that contains information about
    // how system battery metrics are reported.
    BatteryScale: array [0 .. 2] of BATTERY_REPORTING_SCALE;
    // The lowest system sleep state (Sx) that will generate a wake event when
    // the system is on AC power. This member must be one of the
    // SYSTEM_POWER_STATE enumeration type values.
    AcOnLineWake: SYSTEM_POWER_STATE;
    // The lowest system sleep state (Sx) that will generate a wake event via
    // the lid switch. This member must be one of the SYSTEM_POWER_STATE
    // enumeration type values.
    SoftLidWake: SYSTEM_POWER_STATE;
    // To wake the computer using the RTC, the operating system must also
    // support waking from the sleep state the computer is in when the RTC
    // generates the wake event. Therefore, the effective lowest sleep state
    // from which an RTC wake event can wake the computer is the lowest sleep
    // state supported by the operating system that is equal to or higher than
    // the value of RtcWake. To determine the sleep states that the operating
    // system supports, check the SystemS1, SystemS2, SystemS3, and SystemS4 members.
    RtcWake: SYSTEM_POWER_STATE;
    // The minimum allowable system power state supporting wake events.
    // This member must be one of the SYSTEM_POWER_STATE enumeration type values.
    // Note that this state may change as different device drivers are
    // installed on the system.
    MinDeviceWakeState: SYSTEM_POWER_STATE;
    // The default system power state used if an application calls
    // RequestWakeupLatency with LT_LOWEST_LATENCY. This member must be one of
    // the SYSTEM_POWER_STATE enumeration type values.
    DefaultLowLatencyWake: SYSTEM_POWER_STATE;
  end;

  PSYSTEM_POWER_CAPABILITIES = ^SYSTEM_POWER_CAPABILITIES;

type
  TACLineStatus = (
    // battery
    acsOffline = 0,
    // plugged in
    acsOnline = 1,
    acsUnknown = 255);

type
  TBatteryState = (
    // High—the battery capacity is at more than 66 percent
    bsHigh = 1,
    // Low—the battery capacity is at less than 33 percent
    bsLow = 2,
    // Critical—the battery capacity is at less than five percent
    bsCritical = 4,
    bsCharging = 8,
    bsNoSystemBattery = 128,
    // Unknown status—unable to read the battery flag information
    bsUnknown = 255);

  TBatteryStatus = set of TBatteryState;

  function GetPwrCapabilities(lpSystemPowerCapabilities: PSYSTEM_POWER_CAPABILITIES): Boolean; stdcall;
  function IsAdminOverrideActive: Boolean; stdcall;
  function IsPwrHibernateAllowed: Boolean; stdcall;
  function IsPwrShutdownAllowed: Boolean; stdcall;
  function IsPwrSuspendAllowed: Boolean; stdcall;

  // utility
  function IsLidPresent: Boolean;
  function IsRunningMobile: Boolean;
  function IsRunningOnBattery: Boolean;
  function IsPowerBtnPresent: Boolean;
  function IsApmPresent: Boolean;
  function IsUpsPresent: Boolean;
  function IsThermalControl: Boolean;
  function GetACLineStatus: TACLineStatus;
  function GetACLineStatusName(const AACLineStatus: TACLineStatus): string;
  function GetBatteryStatus: TBatteryStatus;
  function GetBatteryStateName(const ABatteryState: TBatteryState): string;
  function GetBatteryStatusStr(const ABatteryState: TBatteryStatus;
    const ADelimiter: Char = ','): string;
  function GetBatteryLifePercent: Byte;
  function GetBatteryLifeTime: DWORD;
  function GetBatteryLifeTimeFull: DWORD;
  function GetNumberOfProcessors: DWORD;
  function GetSystemPowerStateName(const ASystemPowerState: SYSTEM_POWER_STATE): string;

implementation

uses
  SysUtils,
  Classes;

const
  powrproflib = 'powrprof.dll';

function GetPwrCapabilities(lpSystemPowerCapabilities: PSYSTEM_POWER_CAPABILITIES): Boolean; external powrproflib name 'GetPwrCapabilities';
function IsAdminOverrideActive: Boolean; external powrproflib name 'IsAdminOverrideActive';
function IsPwrHibernateAllowed: Boolean; external powrproflib name 'IsPwrHibernateAllowed';
function IsPwrShutdownAllowed: Boolean; external powrproflib name 'IsPwrShutdownAllowed';
function IsPwrSuspendAllowed: Boolean; external powrproflib name 'IsPwrSuspendAllowed';

function IsLidPresent: Boolean;
var
  LSYSTEM_POWER_CAPABILITIES: SYSTEM_POWER_CAPABILITIES;
begin
  Result := GetPwrCapabilities(@LSYSTEM_POWER_CAPABILITIES);
  if Result then
    Result := LSYSTEM_POWER_CAPABILITIES.LidPresent;
end;

function IsRunningMobile: Boolean;
begin
  Result := IsLidPresent or IsRunningOnBattery;
end;

function IsRunningOnBattery: Boolean;
begin
  Result := (GetACLineStatus = acsOffline);
end;

function IsPowerBtnPresent: Boolean;
var
  LSYSTEM_POWER_CAPABILITIES: SYSTEM_POWER_CAPABILITIES;
begin
  Result := GetPwrCapabilities(@LSYSTEM_POWER_CAPABILITIES);
  if Result then
    Result := LSYSTEM_POWER_CAPABILITIES.PowerButtonPresent;
end;

function IsApmPresent: Boolean;
var
  LSYSTEM_POWER_CAPABILITIES: SYSTEM_POWER_CAPABILITIES;
begin
  Result := GetPwrCapabilities(@LSYSTEM_POWER_CAPABILITIES);
  if Result then
    Result := LSYSTEM_POWER_CAPABILITIES.ApmPresent;
end;

function IsUpsPresent: Boolean;
var
  LSYSTEM_POWER_CAPABILITIES: SYSTEM_POWER_CAPABILITIES;
begin
  Result := GetPwrCapabilities(@LSYSTEM_POWER_CAPABILITIES);
  if Result then
    Result := LSYSTEM_POWER_CAPABILITIES.UpsPresent;
end;

function IsThermalControl: Boolean;
var
  LSYSTEM_POWER_CAPABILITIES: SYSTEM_POWER_CAPABILITIES;
begin
  Result := GetPwrCapabilities(@LSYSTEM_POWER_CAPABILITIES);
  if Result then
    Result := LSYSTEM_POWER_CAPABILITIES.ThermalControl;
end;

function GetACLineStatus: TACLineStatus;
var
  LSystemPowerStatus: TSystemPowerStatus;
begin
  Result := acsUnknown;
  if GetSystemPowerStatus(LSystemPowerStatus) then
    Result := TACLineStatus(LSystemPowerStatus.ACLineStatus);
end;

function GetACLineStatusName(const AACLineStatus: TACLineStatus): string;
begin
  Result := 'Unknown';
  case AACLineStatus of
    acsOffline: Result := 'Offline';
    acsOnline: Result := 'Online';
  end; // case AACLineStatus of
end;

function GetBatteryStatus: TBatteryStatus;
var
  LSystemPowerStatus: TSystemPowerStatus;

    procedure CheckState(const ABatteryState: TBatteryState);
    begin
      if (LSystemPowerStatus.BatteryFlag and Ord(ABatteryState)) = Ord(ABatteryState) then
        Include(Result, ABatteryState);
    end; // procedure CheckState(const ABatteryState: TBatteryState);

begin
  Result := [];
  if GetSystemPowerStatus(LSystemPowerStatus) then begin
    CheckState(bsHigh);
    CheckState(bsLow);
    CheckState(bsCritical);
    CheckState(bsCharging);
    CheckState(bsNoSystemBattery);
    CheckState(bsUnknown);
  end else
    Result := [bsUnknown];
end;

function GetBatteryStateName(const ABatteryState: TBatteryState): string;
begin
  case ABatteryState of
    bsHigh: Result := 'High';
    bsLow: Result := 'Low';
    bsCritical: Result := 'Critical';
    bsCharging: Result := 'Charging';
    bsNoSystemBattery: Result := 'No system battery';
    bsUnknown: Result := 'Unknown';
  end; // case ABatteryState of
end;

function GetBatteryStatusStr(const ABatteryState: TBatteryStatus;
  const ADelimiter: Char): string;
var
  LBatteryState: TBatteryState;
  LNames: TStringList;
begin
  Result := EmptyStr;
  LNames := TStringList.Create;
  try
    LNames.Delimiter := ADelimiter;
    for LBatteryState in ABatteryState do
      LNames.Add(GetBatteryStateName(LBatteryState));
    Result := LNames.DelimitedText;
  finally
    FreeAndNil(LNames);
  end; // tryf
end;

function GetBatteryLifePercent: Byte;
var
  LSystemPowerStatus: TSystemPowerStatus;
begin
  Result := 0;
  if GetSystemPowerStatus(LSystemPowerStatus) then
    // The percentage of full battery charge remaining.
    // This value in the range 0 to 100 or 255 if status is unknown.
    Result := LSystemPowerStatus.BatteryLifePercent;
end;

function GetBatteryLifeTime: DWORD;
var
  LSystemPowerStatus: TSystemPowerStatus;
begin
  Result := DWORD(-1);
  if GetSystemPowerStatus(LSystemPowerStatus) then
    // The number of seconds of battery life remaining,
    // or –1 if remaining seconds are unknown.
    Result := LSystemPowerStatus.BatteryLifeTime;
end;

function GetBatteryLifeTimeFull: DWORD;
var
  LSystemPowerStatus: TSystemPowerStatus;
begin
  Result := DWORD(-1);
  if GetSystemPowerStatus(LSystemPowerStatus) then
    // The number of seconds of battery life when at full charge,
    // or –1 if full battery lifetime is unknown.
    Result := LSystemPowerStatus.BatteryFullLifeTime;
end;

function GetNumberOfProcessors: DWORD;
var
  LSystemInfo: TSystemInfo;
begin
  GetSystemInfo(LSystemInfo);
  // number of processor means number of threads
  // i.e. a processor with 4 cores can have 8 threads
  Result := LSystemInfo.dwNumberOfProcessors;
end;

function GetSystemPowerStateName(const ASystemPowerState: SYSTEM_POWER_STATE): string;
begin
  Result := SYSTEM_POWER_STATE_NAMES[ASystemPowerState];
end;

end.
How to use it:
a) drop a memo and a button on the form, rename the memo to "edInfo"
b) double-click the button and copy-paste the following code
procedure TForm1.Button1Click(Sender: TObject);

  procedure AddBool(const s: string; const Value: Boolean);
  begin
    edInfo.Lines.Add(Format('%s = %s', [s, BoolToStr(Value, True)]));
  end; // procedure AddBool(const s: string; const Value: Boolean);

  procedure AddString(const s, Value: string);
  begin
     edInfo.Lines.Add(Format('%s = %s', [s, Value]));
  end; // procedure AddString(const s, Value: string);

  procedure AddPercent(const s: string; const Value: Byte);
  begin
    edInfo.Lines.Add(Format('%s = %d%%', [s, Value]));
  end; // procedure AddPercent(const s: string; const Value: Byte);

  procedure AddSeconds(const s: string; const Value: DWORD);
  begin
    edInfo.Lines.Add(Format('%s = %d sec.', [s, Value]));
  end; // procedure AddSeconds(const s: string; const Value: DWORD);

  procedure AddDWord(const s: string; const Value: DWORD);
  begin
    edInfo.Lines.Add(Format('%s = %d', [s, Value]));
  end; // procedure AddDWord(const s: string; const Value: DWORD);

begin
  edInfo.Clear;
  AddBool('IsLidPresent', IsLidPresent);
  AddBool('IsRunningMobile', IsRunningMobile);
  AddBool('IsRunningOnBattery', IsRunningOnBattery);
  AddBool('IsPowerBtnPresent', IsPowerBtnPresent);
  AddBool('IsApmPresent', IsApmPresent);
  AddBool('IsUpsPresent', IsUpsPresent);
  AddBool('IsThermalControl', IsThermalControl);
  AddString('GetACLineStatus', GetACLineStatusName(GetACLineStatus));
  AddString('GetBatteryStatusStr', GetBatteryStatusStr(GetBatteryStatus));
  AddPercent('GetBatteryLifePercent', GetBatteryLifePercent);
  // if GetBatteryLifeTime = -1 it means that laptop is either plugged in OR
  // it is running on battery for a few seconds -- Windows did NOT detect
  // yet or it can't tell for certain how many seconds left
  // also the value might increase in a couple of seconds
  AddSeconds('GetBatteryLifeTime', GetBatteryLifeTime);
  // in my tests GetBatteryLifeTimeFull retrieves only -1 it might have something
  // to do with the fact that my laptop is only a couple of days old
  // or something fails -- I'm NOT 100% sure on this, please feel free to comment
  AddSeconds('GetBatteryLifeTimeFull', GetBatteryLifeTimeFull);
  AddDWord('GetNumberOfProcessors', GetNumberOfProcessors);
end;
c) and last but not least HAVE FUN!!

Blogroll(General programming and Delphi feeds)