unit main;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SKYPE4COMLib_TLB, StdCtrls, ExtCtrls, setupapi, {MidasLib,}
CRTL, Menus, ComCtrls, ImgList, Buttons, Grids, DBGrids, ToolWin, ShellApi,
IdBaseComponent, IdComponent,
IdCustomTCPServer, IdTCPServer, IdContext,
SHFolder, IniFiles, {stopwatch,}
CPort, CPortCtl, LBDSystem, DB, DBClient, DBCtrls, sSkinManager, sPanel, sDBNavigator, acDBGrid, sScrollBox,
sPageControl, acAlphaImageList, acProgressBar, sSpeedButton, sGroupBox, sTreeView, sBitBtn, sCheckBox, sListBox,
sComboBox, sRadioButton, sButton, sMemo, sSpinEdit, sEdit, sLabel, {sHintManager,} ValEdit, sListView, IdGlobal;
type
Tfrm_main = class(TForm)
ComPort_Modem: TComPort;
ComPort_AI: TComPort;
ComDataPacket_RING: TComDataPacket;
ComPort_UI: TComPort;
ComDataPacket_Number: TComDataPacket;
ComDataPacket_320: TComDataPacket;
ComDataPacket_End: TComDataPacket;
ComDataPacket_Connect: TComDataPacket;
ds_gsm2skype: TDataSource;
pum_main: TPopupMenu;
pum_RefreshSkypeContacts: TMenuItem;
Skin: TsSkinManager;
Panel_Status: TsPanel;
Pages: TsPageControl;
Page_Main: TsTabSheet;
Page_Routing: TsTabSheet;
Page_Log: TsTabSheet;
il_24: TsAlphaImageList;
sb_skype: TsSpeedButton;
il_skype: TsAlphaImageList;
il_modem: TsAlphaImageList;
sb_modem: TsSpeedButton;
ComDataPacket_Signal: TComDataPacket;
sb_system: TsSpeedButton;
il_system: TsAlphaImageList;
Tabs: TsPageControl;
Tab_Main: TsTabSheet;
Tab_System: TsTabSheet;
Tab_Modem: TsTabSheet;
chk_useskin: TsCheckBox;
chk_autostart: TsCheckBox;
chk_startminimized: TsCheckBox;
chk_BoostFromModem: TsCheckBox;
chk_SmoothFromModem: TsCheckBox;
Tab_IncomingGSM: TsTabSheet;
cbox_IncomingMode: TsComboBox;
cbox_IncomingTransferTo: TsComboBox;
Tab_IncomingSMS: TsTabSheet;
cbox_IncomingSMSMode: TsComboBox;
cbox_IncomingSMSTransferTo: TsComboBox;
ComDataPacket_SMSCame: TComDataPacket;
ComDataPacket_SMSReceived: TComDataPacket;
Tab_Events: TsTabSheet;
cbox_EventsMode: TsComboBox;
cbox_EventsTransferTo: TsComboBox;
Memo_Log: TsMemo;
Tab_Admins: TsTabSheet;
lbox_Admins: TsListBox;
lbox_SkypeUsers: TsListBox;
Tab_Restrictions: TsTabSheet;
edt_codes: TsEdit;
chk_SMSFollowToGSM: TsCheckBox;
pnl_minmaxCodes: TsPanel;
edt_Max: TsDecimalSpinEdit;
edt_Min: TsDecimalSpinEdit;
Tab_Safety: TsTabSheet;
chk_UsePrefix: TsCheckBox;
edt_Prefix: TsEdit;
sPanel1: TsPanel;
tmr_GetInfoFromModem: TTimer;
ComDataPacket_OperatorName: TComDataPacket;
cbox_ModemNetworkMode: TsComboBox;
RouteTable: TsListView;
cbox_RouteTable: TsComboBox;
AddRecord1: TMenuItem;
DeleteRecord1: TMenuItem;
N1: TMenuItem;
N2: TMenuItem;
sb_SaveAll: TsSpeedButton;
Procedure SaveRouteTable;
Procedure LoadRouteTable;
Procedure SaveListViewToFile(AListView: TsListView; sFileName: string);
Procedure LoadListViewToFile(AListView: TsListView; sFileName: string);
Function LocateGSM(AListView: TsListView; Number: string) : String;
Procedure CancelAllSkypeCalls;
Procedure ChangeBusy(Sender: TObject);
Procedure InitComPorts;
Procedure InServerConnect(AContext: TIdContext);
Procedure InServerDisconnect(AContext: TIdContext);
Procedure InServerExecute(AContext: TIdContext);
Procedure OutServerConnect(AContext: TIdContext);
Procedure OutServerDisconnect(AContext: TIdContext);
Procedure OutServerExecute(AContext: TIdContext);
Procedure SpkServerConnect(AContext: TIdContext);
Procedure SpkServerDisconnect(AContext: TIdContext);
Procedure SpkServerExecute(AContext: TIdContext);
Procedure SkypeCallStatus(Sender: TObject; const pCall: ICall;
Status: TOleEnum);
Procedure SkypeMessageStatus(Sender: TObject; const pMessage: IChatMessage;
Status: TChatMessageStatus);
Procedure SkypeAttachmentStatus(Sender: TObject; Status: TOleEnum);
Procedure RefreshSkypeContacts;
Procedure Log(S: String);
procedure FormCreate(Sender: TObject);
procedure InitSockets;
Procedure DeleteSockets;
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure ComDataPacket_RINGPacket(Sender: TObject; const Str: string);
procedure ComDataPacket_NumberPacket(Sender: TObject; const Str: string);
procedure ComDataPacket_320Packet(Sender: TObject; const Str: string);
procedure ComDataPacket_EndPacket(Sender: TObject; const Str: string);
procedure ComDataPacket_ConnectPacket(Sender: TObject; const Str: string);
procedure pum_RefreshSkypeContactsClick(Sender: TObject);
procedure pum_SaveTableClick(Sender: TObject);
procedure SkinGetMenuExtraLineData(FirstItem: TMenuItem; var SkinSection, Caption: string;
var Glyph: TBitmap; var LineVisible: Boolean);
procedure sb_skypeClick(Sender: TObject);
procedure ComDataPacket_SignalPacket(Sender: TObject; const Str: string);
procedure chk_useskinClick(Sender: TObject);
procedure cbox_IncomingModeChange(Sender: TObject);
procedure cbox_IncomingSMSModeChange(Sender: TObject);
procedure ComDataPacket_SMSCamePacket(Sender: TObject; const Str: string);
procedure ComDataPacket_SMSReceivedPacket(Sender: TObject; const Str: string);
procedure cbox_EventsModeChange(Sender: TObject);
procedure lbox_AdminsDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure lbox_AdminsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure lbox_SkypeUsersDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure lbox_SkypeUsersDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
procedure chk_UsePrefixClick(Sender: TObject);
procedure ComPort_UIAfterOpen(Sender: TObject);
procedure tmr_GetInfoFromModemTimer(Sender: TObject);
procedure ComDataPacket_OperatorNamePacket(Sender: TObject; const Str: string);
Function ChangeNetworkMode(I:Integer): String;
procedure cbox_ModemNetworkModeChange(Sender: TObject);
Procedure LoadIni;
Procedure SaveIni;
Procedure ReInitModem;
procedure pum_SaveAdjustmentsClick(Sender: TObject);
Procedure PlaceCalltoSkype(FromGSM, ToSkype : String; Direction : Integer);
procedure chk_BoostFromModemClick(Sender: TObject);
procedure chk_SmoothFromModemClick(Sender: TObject);
Procedure ReInitStreams;
procedure Memo_LogChange(Sender: TObject);
procedure RouteTableSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
procedure cbox_RouteTableKeyPress(Sender: TObject; var Key: Char);
procedure AddRecord1Click(Sender: TObject);
procedure DeleteRecord1Click(Sender: TObject);
procedure cbox_RouteTableExit(Sender: TObject);
procedure sb_SaveAllClick(Sender: TObject);
procedure sb_systemClick(Sender: TObject);
private
Skype: TSkype;
MicInServer: TIdTCPServer;
MicOutServer: TIdTCPServer;
SpeakerServer: TIdTCPServer;
OutContext: TIdContext;
InContext: TIdContext;
SpkContext: TIdContext;
Call: ICall;
public
{ Public declarations }
end;
Type
TIntegers = Array of SmallInt; // Тип для работы с байтовыми буферами, как с Integer
Const
{$include sounds.inc} // Звуки в массивах
Const
Protocol = 8; // Версия протокола API Скайпа
MicInPort = 13754; // Порт микрофонного входа Скайпа
MicOutPort = 13755; // Порт микрофонного выхода Скайпа
SpeakerPort = 13756; // Порт выхода звука из Скайпа
const
PortsGUID: TGUID = '{4D36E978-E325-11CE-BFC1-08002BE10318}'; // ports
ModemsGUID: TGUID = '{4D36E96D-E325-11CE-BFC1-08002BE10318}'; // modems
// Это работает с Е1550
//PortName_Modem = 'HUAWEI Mobile Connect - 3G Modem';
//PortName_AI = 'HUAWEI Mobile Connect - 3G Application Interface';
//PortName_UI = 'HUAWEI Mobile Connect - 3G PC UI Interface';
// Это работает с Е3531ы
PortName_Modem = 'Mobile Connect - Modem';
PortName_AI = 'Mobile Connect - Application Interface';
PortName_UI = 'Mobile Connect - PC UI Interface';
Const
MaxLenBuff = 65535; // Размер буфера, больше размера, кторый может установить Скайп в два раза
Const
AppName = 'LongBridgeDigital'; // Имя программы
LogDirName = 'logs'; // Имя подддиректории логов
RouteTableFileName = 'routetable.dat'; // Имя файла таблицы роутинга
IniFileName = AppName + '.ini'; // Имя INI файла
Const
IVRCode = '@IVR';
Var
AppDirectory : String = ''; // Путь до директории программы, с '\', определяется после запуска
AppLogDirectory : String = ''; // Полный путь до директории логов, с обратным слешем, определяется после запуска
Const
WaitAfterSent = 20; // Ожидание в мс после отправки в модем
var
frm_main: Tfrm_main;
Port_Modem, Port_AI, Port_UI: String;
ResampledToModem: TMemoryStream; // Стрим, в который пишутся данные после ресемплинга из 16000 в 80000
RAWDataFromModem: TMemoryStream; // Сырые данные от модема
PacketSize: Integer; // Размер пакета, который установил Скайп
BuffSpk: TidBytes; // Буфер голоса для чтения из спикеров
BuffMic: TidBytes; // Буфер голоса в микрофонный вход скайпа
BuffSize: Integer; // Размер буфера глобальный
BuffMicSize : Integer; // Размер буфера от микрофона
BuffSpkSize : Integer; // Размер буфера от спикеров скайпа
SkypeToModemBuff: Array [0 .. MaxLenBuff] of Byte;
ModemToSkypeBuff: Array [0 .. MaxLenBuff] of Byte;
tomodem: Array [0 .. 319] of Byte; // Массив для отправки в модем
frommodem: Array [0 .. 319] of Byte; // Массив для приема из модема
FromModemVolumeUp: Boolean = True; // Усиление звука от модема
FromModemSmooth: Boolean = True; // Сглаживание звука от модема
LBDSystem: TLBDSystem; // LongBridgeDigital главный объект
MySkypeName : String;
implementation
{$R *.dfm}
{$INCLUDE routines.inc} // Функции и процедуры, которые не относятся к форме
Procedure Tfrm_main.SaveListViewToFile(AListView: TsListView; sFileName: string);
Var
S: string;
SP: TStringList;
I, J: integer;
begin
if AListView.Items.Count>0 then begin
sp:=TStringList.Create;
for i:=0 to AListView.Items.Count-1 do begin
s:=AListView.Items[i].Caption;
for j:=0 to AListView.Items[i].SubItems.Count-1 do
s:=s+'|'+AListView.Items[i].SubItems[j];
sp.Add(s)
end;
sp.SaveToFile(sFileName);
sp.Free;
end;
end;
Procedure Tfrm_main.LoadListViewToFile(AListView: TsListView; sFileName: string);
Var
S:string;
SP: TStringList;
I: integer;
begin
if fileexists(sFileName) then
Begin
Sp:=TStringList.Create;
sp.LoadFromFile(sFileName);
if sp.Count>0 then begin
AListView.Clear;
for i:=0 to sp.Count-1 do begin
s:=sp.Strings[i];
AListView.Items.Add.Caption:=copy(s,1,pos('|',s)-1);
delete(s,1,pos('|',s));
while pos('|',s)<>0 do begin
AListView.Items[AListView.Items.Count-1].SubItems.add(copy(s,1,pos('|',s)-1));
delete(s,1,pos('|',s));
end;
AListView.Items[AListView.Items.Count-1].SubItems.add(s);
end;
end;
sp.Free;
end;
end;
Function GetFileNameFromDateTime(DT: TDateTime) : String;
var
da : Array[0..6] of Word;
x : Integer;
Y, M, D, H, Mn, S, mS : Word;
Str : String;
begin
DecodeDate(DT, Y, M ,D);
DecodeTime(Now, H, Mn, S, mS);
da[0] := Y;
da[1] := M;
da[2] := D;
da[3] := H;
da[4] := Mn;
da[5] := S;
Str := '';
for x := 0 to 4 do
if da[x] < 9 then Str := Str + '0' + IntToStr(da[x]) + '-'
else Str := Str + IntToStr(da[x]) + '-';
if da[5] < 9 then Str := Str + '0' + IntToStr(da[5])
else Str := Str + IntToStr(da[5]);
Result := Str + '.log';
end;
Procedure Tfrm_main.ReInitStreams;
var
x : Integer;
begin
ResampledToModem.Clear;
RAWDataFromModem.Clear;
for x := 0 to Length(SkypeToModemBuff) do SkypeToModemBuff[x] := 0;
for x := 0 to Length(ModemToSkypeBuff) do ModemToSkypeBuff[x] := 0;
end;
Function Tfrm_main.ChangeNetworkMode(I:Integer): String;
begin
case I of
0 : Result := 'AT^SYSCFG=13,1,3fffffff,0,0' + #13; // 2G Only
1 : Result := 'AT^SYSCFG=2,1,3fffffff,0,0' + #13; // 2G Preffered
2 : Result := 'AT^SYSCFG=14,2,3fffffff,0,1' + #13; // 3G Only
3 : Result := 'AT^SYSCFG=2,2,3fffffff,0,1' + #13; // 3G Preffered
4 : Result := 'AT^SYSCFG=2,2,3fffff ff,0,2' + #13; // Both 2G and 3G
end;
end;
Procedure Tfrm_main.SaveRouteTable;
begin
//cds_gsm2skype.SaveToFile(AppDirectory + RouteTableFileName); // Сохраняем в МОИ ДОКУМЕНТЫ\Имя программы
SaveListViewToFile(RouteTable, AppDirectory + RouteTableFileName);
end;
Procedure Tfrm_main.LoadRouteTable;
begin
LoadListViewToFile(RouteTable, AppDirectory + RouteTableFileName);
end;
Function Tfrm_main.LocateGSM(AListView: TsListView; Number: string) : String;
var
x : Integer;
begin
Result := '';
if AListView.Items.Count > 0 then // Если записи есть
for x := 0 to AListView.Items.Count - 1 do // Начинаем искать по всем
if Number = AListView.Items.Item[x].Caption then // Если найдена запись
Result := AListView.Items.Item[x].SubItems[0] // Выводим субитем в результат
end;
procedure Tfrm_main.sb_SaveAllClick(Sender: TObject);
begin
SaveRouteTable;
SaveIni;
end;
procedure Tfrm_main.sb_skypeClick(Sender: TObject);
begin
if Skype.AttachmentStatus = apiAttachSuccess then RefreshSkypeContacts;
end;
procedure Tfrm_main.sb_systemClick(Sender: TObject);
begin
if LBDSystem.Busy then LBDSystem.Busy := False;
end;
procedure Tfrm_main.AddRecord1Click(Sender: TObject);
var
Item: TListItem;
begin
Item := TListItem.Create(RouteTable.Items); // инициализируешь новую строку
Item.Caption := '+xxxyyzzzz'; // заполнаяешь
Item.SubItems.Add('echo123'); // можно проделать в цикле
RouteTable.Items.Insert(0); // добавляешь пустую сроку наверх
RouteTable.Items.Item[0] := Item; // и вписываешь в нее свою
Item.Free; // освобождаешь строку
end;
Procedure Tfrm_main.CancelAllSkypeCalls;
var
x: Integer;
begin
if Skype.ActiveCalls.Count > 0 then
for X := 1 to Skype.ActiveCalls.Count do
TRY
Skype.ActiveCalls[x].Finish;
EXCEPT
//nothing
END;
end;
Procedure Tfrm_main.RefreshSkypeContacts;
var
x: Integer;
SkypeUsers : TStringList;
begin
SkypeUsers := TStringList.Create;
TRY
if Skype.AttachmentStatus = apiAttachSuccess
then
for x := 1 to Skype.Friends.Count do
if not Skype.Friends.Item[x].IsSkypeOutContact
then SkypeUsers.Add(Skype.Friends.Item[x].Handle);
EXCEPT
on E : Exception do Log(E.ClassName + ' ' + E.Message);
END;
SkypeUsers.Sort;
cbox_IncomingTransferTo.Items.Assign(SkypeUsers);
cbox_IncomingTransferTo.Items.Insert(0, IVRCode); // Добавляем IVR в начало
cbox_RouteTable.Items.Assign(cbox_IncomingTransferTo.Items); // Берем уже с IVR
cbox_IncomingSMSTransferTo.Items.Assign((SkypeUsers));
cbox_EventsTransferTo.Items.Assign((SkypeUsers));
lbox_SkypeUsers.Items.Assign(SkypeUsers);
SkypeUsers.Free;
end;
procedure Tfrm_main.cbox_EventsModeChange(Sender: TObject);
begin
case cbox_EventsMode.ItemIndex of
0..1 : cbox_EventsTransferTo.Enabled := False;
2..3 : cbox_EventsTransferTo.Enabled := True;
end;
end;
procedure Tfrm_main.cbox_IncomingModeChange(Sender: TObject);
begin
{
Режимы реагирования на входящие звонки:
0 - Игнорировать все звонки
1 - Перенаправлять, если адресат есть в таблице роутинга
2 - Перенаправлять, если адресат есть в таблице роутинга, если в таблице нет - переадресовывать на указанный Скайп аккаунт
3 - Переадресовывать все на указанный Скайп аккаунт
}
case cbox_IncomingMode.ItemIndex of
0..1 : cbox_IncomingTransferTo.Enabled := False;
2..3 : cbox_IncomingTransferTo.Enabled := True;
end;
end;
procedure Tfrm_main.cbox_IncomingSMSModeChange(Sender: TObject);
begin
{
Режимы реагирования на входящие СМС:
0 - Игнорировать все сообщения
1 - Перенаправлять, если адресат есть в таблице роутинга
2 - Перенаправлять, если адресат есть в таблице роутинга и так же отправлять на указанный Скайп аккаунт
3 - Перенаправлять все только на определенный Скайп - аккаунт
Все входящие СМС после обработки процедурой стираются.
}
case cbox_IncomingSMSMode.ItemIndex of
0..1 : cbox_IncomingSMSTransferTo.Enabled := False;
2..3 : cbox_IncomingSMSTransferTo.Enabled := True;
end;
end;
procedure Tfrm_main.cbox_ModemNetworkModeChange(Sender: TObject);
begin
if ComPort_UI.Connected then
ComPort_UI.WriteStr(ChangeNetworkMode(cbox_ModemNetworkMode.ItemIndex));
end;
procedure Tfrm_main.cbox_RouteTableExit(Sender: TObject);
begin
cbox_RouteTable.Visible := False;
end;
procedure Tfrm_main.cbox_RouteTableKeyPress(Sender: TObject; var Key: Char);
begin
case Key of
Char(VK_RETURN) : begin
if RouteTable.ItemIndex >= 0 then
RouteTable.Selected.SubItems[0] := cbox_RouteTable.Text;
cbox_RouteTable.Visible := False;
end;
Char(VK_ESCAPE) : cbox_RouteTable.Visible := False;
end;
end;
procedure Tfrm_main.chk_useskinClick(Sender: TObject);
begin
Skin.Active := chk_useskin.Checked;
end;
procedure Tfrm_main.chk_BoostFromModemClick(Sender: TObject);
begin
FromModemVolumeUp := chk_BoostFromModem.Checked;
end;
procedure Tfrm_main.chk_SmoothFromModemClick(Sender: TObject);
begin
FromModemSmooth := chk_BoostFromModem.Checked;
end;
procedure Tfrm_main.chk_UsePrefixClick(Sender: TObject);
begin
edt_Prefix.Enabled := chk_UsePrefix.Checked;
end;
Procedure Tfrm_main.PlaceCalltoSkype(FromGSM: string; ToSkype: string; Direction : Integer);
begin
Log('Direct.' + IntToStr(Direction) + ' call from GSM (' + FromGSM + ') to Skype: ' + ToSkype);
TRY
//Skype.CurrentUserProfile.FullName := FromGSM;
//Sleep(100);
Skype.SendMessage(ToSkype, 'Incoming GSM call from: ' + FromGSM);
Call := Skype.PlaceCall(ToSkype, '', '', '');
EXCEPT
Log('Error when place call to Skype');
LBDSystem.Busy := False;
END;
end;
Procedure Tfrm_main.ChangeBusy(Sender: TObject);
var
x: Integer;
begin
case LBDSystem.Busy of
True:
begin
Log('System is busy');
sb_system.ImageIndex := 1;
ReInitStreams; // Очищаем все буферы
if LBDSystem.Direction = 0 then //
LBDSystem.Busy := False; // Сбасываем все входящие
if LBDSystem.Direction = 1 then // Ищем ТОЛЬКО в таблице.
if LocateGSM(RouteTable, LBDSystem.GSMNumber) <> '' then // Если в таблице есть соответствие
if LocateGSM(RouteTable, LBDSystem.GSMNumber) <> IVRCode then // И не IVR
PlaceCalltoSkype(LBDSystem.GSMNumber, LocateGSM(RouteTable, LBDSystem.GSMNumber), LBDSystem.Direction) // Звоним туда
else LBDSystem.Busy := False // Номер есть, но скайп-аккаунт не заполнен
else LBDSystem.Busy := False; // Не найден номер в таблице
// Направление #1
if LBDSystem.Direction = 2 then // Ищем в таблице, если нет - смотрим, куда перенаправить
if LocateGSM(RouteTable, LBDSystem.GSMNumber) <> '' then // Если в таблице есть номер
if LocateGSM(RouteTable, LBDSystem.GSMNumber) <> IVRCode then // И скайп-аккаунт указан
PlaceCalltoSkype(LBDSystem.GSMNumber, LocateGSM(RouteTable, LBDSystem.GSMNumber), LBDSystem.Direction) // Звоним туда
else LBDSystem.Busy := False // Иначе, если номер в таблице есть, но скайп-аккаунт не указан - сбрасываем все. Не ебите мозги
else // В таблице не найден номер, смотрим, указан ли скайп-аккаунт перенаправления звонка
if (cbox_IncomingTransferTo.Text <> '') and
(cbox_IncomingTransferTo.Text <> IVRCode) then // Если указан и не IVR
PlaceCalltoSkype(LBDSystem.GSMNumber, cbox_IncomingTransferTo.Text, LBDSystem.Direction) // Звоним на него
else LBDSystem.Busy := False; // Не указан и здесь - сбрасываем
// Направление #2
if LBDSystem.Direction = 3 then // Игнорируем таблицу, перенаправляем все входящие на один скайп-аккаунт
if (cbox_IncomingTransferTo.Text <> '') and
(cbox_IncomingTransferTo.Text <> IVRCode) then // Если скайп-аккаунт указан и не IVR
PlaceCalltoSkype(LBDSystem.GSMNumber, cbox_IncomingTransferTo.Text, LBDSystem.Direction) // Звоним туда
else LBDSystem.Busy := False; // Иначе сбрасываем
// Направление #3
// Направление 11 - юзер, командой DIAL звонит на номер
if LBDSystem.Direction = 11 then
begin
TRY
Call := Skype.PlaceCall(LBDSystem.CurrentUser, '', '', '');
EXCEPT
Log('Error when place call to Skype');
LBDSystem.Busy := False;
END;
end; // Направление #11
// Callback по команде администратора
if LBDSystem.Direction = 12 then
begin
TRY
Call := Skype.PlaceCall(LBDSystem.CurrentUser, '', '', '');
EXCEPT
Log('Error when place call to Skype');
LBDSystem.Busy := False;
END;
end; // Направление #12
end; // LBDSystem is TRUE
False:
begin
ComPort_UI.WriteStr('AT+CHUP' + #13);
CancelAllSkypeCalls;
ReInitStreams;
ComPort_Modem.ClearBuffer(True, True);
ComPort_AI.ClearBuffer(True, True);
ComPort_UI.ClearBuffer(True, True);
LBDSystem.GSMNumber := '';
LBDSystem.Direction := 0;
LBDSystem.BusyBy := '';
Log('System is free');
sb_system.ImageIndex := 0;
end;
end;
end;
Procedure Tfrm_main.InitSockets;
Begin
MicInServer := TIdTCPServer.Create(Self);
MicOutServer := TIdTCPServer.Create(Self);
SpeakerServer := TIdTCPServer.Create(Self);
MicInServer.DefaultPort := MicInPort;
MicInServer.OnConnect := InServerConnect;
MicInServer.OnDisconnect := InServerDisconnect;
MicInServer.OnExecute := InServerExecute;
MicOutServer.DefaultPort := MicOutPort;
MicOutServer.OnConnect := OutServerConnect;
MicOutServer.OnDisconnect := OutServerDisconnect;
MicOutServer.OnExecute := OutServerExecute;
SpeakerServer.DefaultPort := SpeakerPort;
SpeakerServer.OnExecute := SpkServerExecute;
SpeakerServer.OnConnect := SpkServerConnect;
SpeakerServer.OnDisconnect := SpkServerDisconnect;
MicInServer.Active := True;
MicOutServer.Active := True;
SpeakerServer.Active := True;
End;
procedure Tfrm_main.DeleteRecord1Click(Sender: TObject);
begin
if (RouteTable.ItemIndex >= 0) and (RouteTable.Selected.Index = RouteTable.ItemIndex) then
RouteTable.Items.Delete(RouteTable.ItemIndex);
end;
Procedure Tfrm_main.DeleteSockets;
begin
if MicInServer.Active Then
MicInServer.Active := False;
if MicOutServer.Active Then
MicOutServer.Active := False;
if SpeakerServer.Active then
SpeakerServer.Active := False;
MicInServer.Free;
MicOutServer.Free;
SpeakerServer.Free;
end;
Procedure Tfrm_main.InitComPorts;
begin
ComPort_Modem.Port := Port_Modem;
ComPort_Modem.Connected := True;
ComPort_AI.Port := Port_AI;
ComPort_AI.Connected := True;
ComPort_UI.Port := Port_UI;
ComPort_UI.Connected := True;
// Остальные строки инициализации находятся в методах onAfterOpen
end;
Procedure Tfrm_main.SkypeAttachmentStatus(Sender: TObject; Status: TOleEnum);
Begin
if Status = apiAttachAvailable Then
Skype.Attach(Protocol, False);
Log('Skype attachment status: ' +
Skype.Convert.AttachmentStatusToText(Status));
if Status = apiAttachSuccess Then
begin
MySkypeName := Skype.CurrentUserProfile.FullName;
Log('Skype is connected');
RefreshSkypeContacts;
end;
sb_skype.ImageIndex := Status;
End;
Procedure Tfrm_main.SkypeCallStatus(Sender: TObject; const pCall: ICall; Status: TOleEnum);
Begin
Log('Call status: ' + Skype.Convert.CallStatusToText(Status));
if Status = clsRemoteHold then
begin
Log(LBDSystem.BusyBy + ' paused the conversation'); // BusyBy определился ниже, когда был ответ на звонок
ComPort_UI.WriteStr('AT^DDSETEX=0' + #13); // Выключаем звук от модема
Sleep(WaitAfterSent); // Немного ждем
ReInitStreams; // Очищаем все стримы и буферы
ResampledToModem.Write(Sound_Hold, Length(Sound_Hold)); // Загружаем звук из массива в стрим
ResampledToModem.Position := 0; // Переводим указатель на начало стрима
ComPort_UI.WriteStr('AT^DDSETEX=2' + #13); // Включаем звук на модеме
end;
if Status = clsInProgress Then
Begin
TRY
if LBDSystem.Direction <> 12 then // Если НЕ! Callmeback - перенаправлять в модем, иначе - звук в скайпе по умолчанию
begin
Call.InputDevice[callIoDeviceTypeSoundcard] := '';
Call.CaptureMicDevice[callIoDeviceTypePort] :=
IntToStr(MicInServer.DefaultPort);
Call.InputDevice[callIoDeviceTypePort] :=
IntToStr(MicOutServer.DefaultPort);
Call.OutputDevice[callIoDeviceTypeSoundcard] := '';
Call.OutputDevice[callIoDeviceTypePort] :=
IntToStr(SpeakerServer.DefaultPort);
end;
LBDSystem.BusyBy := Call.PartnerHandle; // Запоминаем, кто занял систему
ReInitStreams; // Освобождаем стримы и буферы
case LBDSystem.Direction of
1..3: begin // Направления входящих звонков от GSM стороны
Log(LBDSystem.GSMNumber + ' >> ' + LBDSystem.BusyBy);
ComPort_UI.WriteStr('ATA' + #13); // Отвечаем на входящий, как только юзер принял Скайп-звонок.
end;
11: begin // Направление исходящих звонков со Скайпа на GSM, инициированые командами Скайп-юзера
Log(LBDSystem.BusyBy + ' >> ' + LBDSystem.GSMNumber);
ComPort_UI.WriteStr('ATD' + LBDSystem.GSMNumber + ';' + #13); // Звоним на GSM
Sleep(WaitAfterSent); // Немножко ждем
ComPort_UI.WriteStr('AT^DDSETEX=2' + #13); // Включаем звук от модема
end;
end;
EXCEPT
Log('Some shit error when Skype inProgress');
END;
End;
if (Status = clsFinished) or
(Status = clsRefused) or
(Status = clsBusy) or
(Status = clsMissed) or
(Status = clsFailed)
Then
Begin
Call := Nil;
PacketSize := 0;
LBDSystem.Busy := False; // Тушим свет. Сеанс закончился
End;
End;
Procedure Tfrm_main.SkypeMessageStatus(Sender: TObject;
const pMessage: IChatMessage; Status: TChatMessageStatus);
{$INCLUDE chkcmd.inc}
var
Answer : String;
begin
If Status = cmsReceived then
begin
LBDSystem.CurrentUser := pMessage.FromHandle;
Log('Received message from: ' + LBDSystem.CurrentUser + ', Text: ' + pMessage.Body);
if CheckCommand(pMessage.Body, Answer, isAdmin(LBDSystem.CurrentUser, lbox_Admins)) > 0 then
Skype.SendMessage(LBDSystem.CurrentUser, Answer);
end;
if Status = cmsSent then
Log('Sending message to: ' + pMessage.FromHandle + ', Text: ' + pMessage.Body);
end;
procedure Tfrm_main.RouteTableSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
var
rct : TRect;
begin
rct := Item.DisplayRect(drSelectBounds);
With cbox_RouteTable do
begin
Visible := False;
Text := item.SubItems[0];
Left := rct.Right + 4;
Top := rct.Top;
Width := RouteTable.Width - rct.Right - 8;
Visible := True;
end;
end;
Procedure Tfrm_main.InServerConnect(AContext: TIdContext);
Begin
Log('In has connected to socket ' + IntToStr(MicInServer.DefaultPort));
InContext := AContext;
End;
Procedure Tfrm_main.OutServerConnect(AContext: TIdContext);
Begin
Log('Out has connected to socket ' + IntToStr(MicOutServer.DefaultPort));
OutContext := AContext;
End;
Procedure Tfrm_main.SpkServerConnect(AContext: TIdContext);
Begin
Log('Spk has connected to socket ' + IntToStr(SpeakerServer.DefaultPort));
SpkContext := AContext;
End;
Procedure Tfrm_main.InServerDisconnect(AContext: TIdContext);
Begin
Log('In has disconnected from socket ' + IntToStr(MicInServer.DefaultPort));
End;
Procedure Tfrm_main.OutServerDisconnect(AContext: TIdContext);
Begin
Log('Out has disconnected from socket ' + IntToStr(MicOutServer.DefaultPort));
End;
Procedure Tfrm_main.SpkServerDisconnect(AContext: TIdContext);
Begin
Log('Spk has disconnected from socket ' +
IntToStr(SpeakerServer.DefaultPort));
End;
Procedure Tfrm_main.InServerExecute(AContext: TIdContext);
Var
b1, b2: Integer;
Begin
if AContext.Connection.IOHandler.InputBufferIsEmpty then
AContext.Connection.IOHandler.CheckForDataOnSource(1);
if AContext.Connection.IOHandler.InputBufferIsEmpty then Exit;
// Reading data from incoming microphone stream.
//BuffMicSize := AContext.Connection.IOHandler.RecvBufferSize;
//AContext.Connection.IOHandler.ReadBytes(BuffMic, BuffMicSize, False);
{
if RAWDataFromModem.Size < BuffSize div 2 then
begin
Sleep(1);
Exit;
end;
}
AContext.Connection.IOHandler.ReadBytes(BuffMic, BuffMicSize, False);
if Call = Nil Then
Exit;
//Log('InExecute');
if PacketSize = 0 Then
Begin
PacketSize := BuffMicSize;
Log('Stream packet size: ' + IntToStr(PacketSize) + ' bytes.');
End;
// Все, что Модем успел записать в стрим, прочитаем и очистим стрим, пусть пишет сначала
RAWDataFromModem.Position := 0;
RAWDataFromModem.Read(ModemToSkypeBuff[0], BuffMicSize div 2);
//Log('From modem stream - ' + IntToStr(RAWDataFromModem.Size));
RAWDataFromModem.Clear;
// Пересемплируем в 16000 Гц
b1 := 0;
b2 := 0;
while b1 <= (BuffMicSize div 2) do
begin
BuffMic[b2 + 0] := ModemToSkypeBuff[b1 + 0];
BuffMic[b2 + 1] := ModemToSkypeBuff[b1 + 1];
BuffMic[b2 + 2] := ModemToSkypeBuff[b1 + 0];
BuffMic[b2 + 3] := ModemToSkypeBuff[b1 + 1];
b1 := b1 + 2;
b2 := b2 + 4;
end;
// Если сглаживание включено, усредним каждый средний семпл
if FromModemSmooth then
begin
b1 := 0;
while b1 <= (BuffMicSize div 2) do
begin
TIntegers(BuffMic)[b1 + 1] := (TIntegers(BuffMic)[b1] + TIntegers(BuffMic)
[b1 + 2]) div 2;
b1 := b1 + 2;
end;
end;
// Если усиление включено, усилим каждый семпл в 10 раз
if FromModemVolumeUp then
For b1 := 0 to (BuffMicSize div 2) do
Begin
b2 := TIntegers(BuffMic)[b1] * 10;
if b2 > 32767 Then
b2 := 32767;
if b2 < -32768 Then
b2 := -32768;
TIntegers(BuffMic)[b1] := b2;
End;
//SetLength(BuffMic, BuffMicSize);
// Отправим результат в микрофонный выход Скайпа
TRY
if OutContext.Connection.Connected Then
OutContext.Connection.IOHandler.Write(BuffMic);
EXCEPT
Log('Out Server is no connected yet!');
END;
//Sleep(10);
//sw.Stop;
//elapsedMiliseconds := sw.ElapsedMiliseconds;
End;
Procedure Tfrm_main.OutServerExecute(AContext: TIdContext);
begin
Sleep(10);
end;
Procedure Tfrm_main.SpkServerExecute(AContext: TIdContext);
Var
b1, b2: Integer;
Begin
if AContext.Connection.IOHandler.InputBufferIsEmpty then
AContext.Connection.IOHandler.CheckForDataOnSource(1);
if AContext.Connection.IOHandler.InputBufferIsEmpty then Exit;
{
if AContext.Connection.IOHandler.RecvBufferSize < BuffSize then
begin
Sleep(1);
Exit;
end;
}
AContext.Connection.IOHandler.ReadBytes(BuffSpk, BuffSpkSize, False);
if Call = Nil Then
Exit;
//Log('SpkExecute');
// Пересемплируем буфер от Скайпа в буфер Модема и запишем его в стрим
b1 := 0;
b2 := 0;
while b1 <= BuffSpkSize do
begin
SkypeToModemBuff[b1 + 0] := BuffSpk[b2 + 0];
SkypeToModemBuff[b1 + 1] := BuffSpk[b2 + 1];
b1 := b1 + 2;
b2 := b2 + 4;
end;
ResampledToModem.Clear;
ResampledToModem.Write(SkypeToModemBuff[0], BuffSpkSize div 2);
//g('To modem stream - ' + IntToStr(ResampledToModem.Size));
ResampledToModem.Position := 0;
//sw.Stop;
//elapsedMiliseconds := sw.ElapsedMiliseconds;
End;
procedure Tfrm_main.lbox_AdminsDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
lbox_Admins.Items.Add(lbox_SkypeUsers.Items[lbox_SkypeUsers.ItemIndex]);
DeleteDuplicates(lbox_Admins);
end;
procedure Tfrm_main.lbox_AdminsDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
begin
Accept := (Source = lbox_SkypeUsers) and (lbox_SkypeUsers.ItemIndex >= 0);
end;
procedure Tfrm_main.lbox_SkypeUsersDragDrop(Sender, Source: TObject; X, Y: Integer);
begin
lbox_Admins.Items.delete(lbox_Admins.ItemIndex);
end;
procedure Tfrm_main.lbox_SkypeUsersDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean);
begin
Accept := (Source = lbox_Admins) and (lbox_Admins.ItemIndex >= 0);
end;
procedure Tfrm_main.tmr_GetInfoFromModemTimer(Sender: TObject);
begin
if ComPort_UI.Connected then
begin
ComPort_UI.WriteStr('AT+COPS=3,0' + #13); // Нахождение имени мобильного оператора, установка формата
ComPort_UI.WriteStr('AT+COPS?' + #13); // Нахождение имени мобильного оператораб в ответе +COPS: 0,0,"Operator",0
ComPort_UI.WriteStr('AT+CSQ' + #13); // Запрос силы сигнала
tmr_GetInfoFromModem.Enabled := True;
end
else
tmr_GetInfoFromModem.Enabled := False;
end;
procedure Tfrm_main.SkinGetMenuExtraLineData(FirstItem: TMenuItem; var SkinSection, Caption: string;
var Glyph: TBitmap; var LineVisible: Boolean);
begin
Caption := 'LongBridge.Digital';
end;
Function ModemIsPresent: Boolean;
function EnumerateUsbCom(fName: String; fGUID: TGUID): String;
var
GUID: TGUID;
PnPHandle: HDevInfo; // handle на базу данных драйверов, раздел ports
i: DWORD;
DeviceInfoData: SP_DEVINFO_DATA;
Err: Integer;
RequiredLength: DWORD;
DevicePath: string;
RegType: DWORD;
Name: ansistring;
// S: string;
// DevPID: Word;
// DevVID: Word;
RegKey: HKey;
begin
LoadSetupApi;
GUID := fGUID;
fName := UpperCase(fName);
Result := '';
PnPHandle := SetupDiGetClassDevs(@GUID, nil, 0,
DIGCF_PRESENT { or DIGCF_DEVICEINTERFACE } );
if PnPHandle = Pointer(INVALID_HANDLE_VALUE) then // не можем открыть базу
raise Exception.Create(SysErrorMessage(GetLastError));
try
i := 0; // первый порт
DeviceInfoData.cbSize := SizeOf(DeviceInfoData);
while SetupDiEnumDeviceInfo(PnPHandle, i, DeviceInfoData) do
// получаем последовательно порты, пока они есть.
begin
DevicePath := '';
Name := '';
// получаем размер строчки HardwareID
SetupDiGetDeviceRegistryProperty(PnPHandle, DeviceInfoData,
{ SPDRP_HARDWAREID } SPDRP_FRIENDLYNAME, RegType, nil, 0,
RequiredLength);
Err := GetLastError;
if Err = ERROR_INSUFFICIENT_BUFFER then
// только эта ошибка должна возникнуть - все другое - что-то не так
begin
if Length(Name) < RequiredLength { div SizeOf(Char) } then
// если буфер маленький, то
SetLength(Name, RequiredLength { div SizeOf(Char)+ 20 } );
// устанавливаем размер буфера
if not SetupDiGetDeviceRegistryProperty(PnPHandle, DeviceInfoData,
{ SPDRP_HARDWAREID } SPDRP_FRIENDLYNAME, RegType, @Name[1],
RequiredLength, RequiredLength) then // получаем HardwareID
begin
inc(i); // если ошибка, то смотрим следущий порт
Continue;
end;
end
else
raise Exception.Create(SysErrorMessage(Err));
Name := UpperCase(Name);
// чтобы сравнивать строки, переводим все в заглавные буквы
if Copy(Name, 1, Length(fName)) = fName then
// если первые три символа HardwareID = 'USB' - то это у нас виртуальный порт
begin
SetLength(DevicePath, 10);
// 10 символов на название ком-порта - хватит (максимальный COM999999 [последний символ = #0])
RegKey := SetupDiOpenDevRegKey(PnPHandle, DeviceInfoData,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
// получаем Handle на раздел реестра экземпляра устройства
if RegKey = INVALID_HANDLE_VALUE then
begin
inc(i); // если ошибка - следущий порт
Continue;
end;
try
RequiredLength := 10 * SizeOf(Char);
if RegQueryValueEx(RegKey, 'PortName', nil, @RegType,
@DevicePath[1], @RequiredLength) <> ERROR_SUCCESS then
// в PortName записано название порта (например - СОМ5)
begin
inc(i);
Continue;
end;
DevicePath := Copy(DevicePath, 1,
RequiredLength div SizeOf(Char) - 1);
TRY
// Result := StrToInt(DevicePath);
Result := DevicePath;
EXCEPT
Result := '';
END;
// результат функции - количество портов для данного VID&PID
finally
RegCloseKey(RegKey); // Handle надо закрыть, даже в случае ошибки
end;
end;
inc(i); // следущий порт
end;
finally
SetupDiDestroyDeviceInfoList(PnPHandle); // освобождаем занятую память.
end;
UnloadSetupApi;
end;
begin
Result := False;
Port_Modem := EnumerateUsbCom(PortName_Modem, ModemsGUID);
Port_AI := EnumerateUsbCom(PortName_AI, PortsGUID);
Port_UI := EnumerateUsbCom(PortName_UI, PortsGUID);
if (Port_Modem = '') or (Port_AI = '') or (Port_UI = '') then
Result := False
else
Result := True;
end;
procedure Tfrm_main.ComDataPacket_320Packet(Sender: TObject; const Str: string);
var
x: Integer;
begin
// Если пакет получен, начинаем писать в стрим для передачи в Скайп
for x := 0 to 319 do
begin
frommodem[x] := Byte(Str[x + 1]);
end;
RAWDataFromModem.Write(frommodem[0], 320);
// Читаем по кольцу. Для отправки информационных сообщений в модем, путем копирования в стрим из другого стрима
if ResampledToModem.Position >= ResampledToModem.Size then ResampledToModem.Position := 0;
// И отправляем из стрима Скайпа в модем
ResampledToModem.Read(tomodem[0], 320);
ComPort_AI.Write(tomodem, 320);
end;
procedure Tfrm_main.ComDataPacket_ConnectPacket(Sender: TObject; const Str: string);
begin
// Связь установлена, разрешаем передавать звук в порт AI
case LBDSystem.Direction of
1..3 : ComPort_UI.WriteStr('AT^DDSETEX=2' + #13);
end;
end;
procedure Tfrm_main.ComDataPacket_EndPacket(Sender: TObject; const Str: string);
begin
// Получена строка ^CEND для первой линии (вторую игнорируем), освобождаем систему
LBDSystem.Busy := False;
end;
procedure Tfrm_main.ComDataPacket_NumberPacket(Sender: TObject;
const Str: string);
begin
// Если система не занята, читаем номер, устанавливаем направление, занимаем систему
if not LBDSystem.Busy then
begin
LBDSystem.GSMNumber := Str;
Log('Incoming GSM call from: ' + LBDSystem.GSMNumber);
LBDSystem.Direction := cbox_IncomingMode.ItemIndex;
LBDSystem.Busy := True;
end;
end;
procedure Tfrm_main.ComDataPacket_OperatorNamePacket(Sender: TObject; const Str: string);
begin
if StrPart('"','"', Str) <> '' then
sb_modem.Caption := ' ' + StrPart('"','"', Str) + ' '
else sb_modem.Caption := '???';
sb_modem.Width := 33 + (Length(sb_modem.Caption) * 6);
end;
procedure Tfrm_main.ComDataPacket_RINGPacket(Sender: TObject;
const Str: string);
begin
// Получили строку RING, узнаем номер
Log('Incoming GSM call');
ComPort_UI.WriteStr('AT+CLIP=1' + #13);
end;
procedure Tfrm_main.ComDataPacket_SignalPacket(Sender: TObject; const Str: string);
var
x: Integer;
begin
// Сила сигнала модема
sb_modem.Grayed := False;
if StrPart(' ', ',', Str) <> '' then
TRY
x := StrToInt(StrPart(' ', ',', Str));
sb_modem.Hint := IntToStr(x);
x := x div 7;
if x <= 4 then sb_modem.ImageIndex := x
else sb_modem.Grayed := True;
EXCEPT
sb_modem.Grayed := True;
END;
end;
procedure Tfrm_main.ComDataPacket_SMSCamePacket(Sender: TObject; const Str: string);
begin
// Получили строку ^CMTI
Log('A SMS is came');
ComPort_UI.WriteStr('AT+CMGF=1' + #13); // Переводим в текстовый режим
ComPort_UI.WriteStr('AT+CMGR=0' + #13); // Читаем первое сообщение
end;
procedure Tfrm_main.ComDataPacket_SMSReceivedPacket(Sender: TObject; const Str: string);
var
sms_fromwhom, sms_text, sms_towhom : String;
begin
{
+CMGR: "REC READ","+380637890072",,"12/09/30,23:40:12+12"
0415044904350020043E04340438043D00200442043504410442
OK
}
// Принимаем только одно сообщение, обрабатываем и стираем все. Тут не смс центр нахуй.
sms_fromwhom := '';
sms_text := '';
sms_fromwhom := StrPart('","', '",,"', Str); // Узнаем, от кого сообщение
sms_text := UCSToAnsi(StrPart('"' + #13#10, #13#10#13#10 + 'OK', Str)); // Вырезаеи м декодируем сообщение
// Если не декодируется, значит там чистый инглишь, оставляем, как есть
if Length(sms_text) = 0 then sms_text := StrPart('"' + #13#10, #13#10#13#10 + 'OK', Str);
Log('Incoming SMS from: ' + sms_fromwhom);
Log('Text: ' + sms_text);
Log(IntToStr(cbox_IncomingSMSMode.ItemIndex));
// Смотрим, куда отправить сообщение
sms_towhom := LocateGSM(RouteTable, sms_fromwhom);
case cbox_IncomingSMSMode.ItemIndex of
0 : begin // Не принимаем СМС
// Никуда не отправляем
end;
1 : begin // Отправляем только, если есть в таблице
// Смотрим в таблицу
if (sms_towhom <> '') and (sms_towhom <> IVRCode) then
begin
Log('Sending.1 SMS from (' + sms_fromwhom + ') to Skype: ' + sms_towhom);
Skype.SendMessage(sms_towhom, 'Incoming SMS from ' + sms_fromwhom + #10 + sms_text);
end; // Если не заполнен Скайп-аккаунт или не найден номер в таблице - выходим
end; // Условие #2
2 : begin // Ищем в таблице, если нет - перенаправляем
if (sms_towhom <> '') and (sms_towhom <> IVRCode) then
begin
Log('Sending.2 SMS from (' + sms_fromwhom + ') to Skype: ' + sms_towhom);
Skype.SendMessage(sms_towhom, 'Incoming SMS from ' + sms_fromwhom + #10 + sms_text);
end
else // Нет в таблице или криво заполнено, смотрим, что в перенаправлении
if (cbox_IncomingSMSTransferTo.Text <> '') and (cbox_IncomingSMSTransferTo.Text <> IVRCode) then
begin
Log('Sending.2 SMS from (' + sms_fromwhom + ') to Skype: ' + cbox_IncomingSMSTransferTo.Text);
Skype.SendMessage(cbox_IncomingSMSTransferTo.Text, 'Incoming SMS from ' + sms_fromwhom + #10 + sms_text);
end;
end; // Условие #2
3 : begin // В таблицу не смотрим, перенаправляем
if (cbox_IncomingSMSTransferTo.Text <> '') and (cbox_IncomingSMSTransferTo.Text <> IVRCode) then
begin
Log('Sending.3 SMS from (' + sms_fromwhom + ') to Skype: ' + cbox_IncomingSMSTransferTo.Text);
Skype.SendMessage(cbox_IncomingSMSTransferTo.Text, 'Incoming SMS from ' + sms_fromwhom + #10 + sms_text);
end;
end; // Условие #3
end; // CASE
ComPort_UI.WriteStr('AT+CMGD=0,4' + #13); // Стираем все сообщения
end;
procedure Tfrm_main.ComPort_UIAfterOpen(Sender: TObject);
begin
ReInitModem;
end;
Procedure Tfrm_main.ReInitModem;
begin
ComPort_UI.WriteStr(ChangeNetworkMode(cbox_ModemNetworkMode.ItemIndex));
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CREG=1' + #13); // Разрешение регистрации в сети
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CSSN=1,1' + #13); // ХЗ что такое
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CMEE=1' + #13); // Индикация сообщений об ошибках
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('ATE0' + #13); // Отключение эха
Sleep(WaitAfterSent);
//ComPort_UI.WriteStr('AT^HS=0,0' + #13); // Высокая скорость. ХЗ
//ComPort_UI.WriteStr('AT+CFUN=1'); // Полная перезагрузка модема
ComPort_UI.WriteStr('AT+CCWA=1' + #13); // Ожидание звонка
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CLIP=1' + #13); // Определение номера
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CNMI=2,1,2,2,0' + #13); // Отображение входящих СМС (+CMTI: "SM",0)
Sleep(WaitAfterSent);
ComPort_UI.WriteStr('AT+CPMS="SM","SM","SM"' + #13); // Все сообщения на Сим карте
Sleep(WaitAfterSent);
//ComPort_UI.WriteStr('AT+CPBS="SM"' + #13); // Телефонная книга на сим карте
ComPort_UI.WriteStr('AT+CMGD=0,4' + #13); // Удаляем все СМС
tmr_GetInfoFromModem.Enabled := True;
end;
procedure Tfrm_main.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
DeleteSockets;
if ComPort_Modem.Connected then
ComPort_Modem.Connected := False;
if ComPort_AI.Connected then
ComPort_AI.Connected := False;
if ComPort_UI.Connected then
ComPort_UI.Connected := False;
ResampledToModem.Free;
RAWDataFromModem.Free;
SaveRouteTable;
SaveIni;
LBDSystem.Free;
Memo_Log.Lines.SaveToFile(AppLogDirectory + GetFileNameFromDateTime(Now));
CanClose := True;
end;
procedure Tfrm_main.FormCreate(Sender: TObject);
var
x: Integer;
begin
if not ModemIsPresent then
begin
ShowMessage('Modem not found');
TerminateProcess(GetCurrentProcess, 0);
end
else
begin
// Получаем или создаем свою папку у юзера в каталоге
if not DirectoryExists(GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName) then
CreateDir(GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName);
AppDirectory := GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName + '\';
// Получаем или создаем папку логов у юзера в каталоге
if not DirectoryExists(GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName + '\' + LogDirName) then
CreateDir(GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName + '\' + LogDirName);
AppLogDirectory := GetSpecialFolderPath(CSIDL_PERSONAL) + '\' + AppName + '\' + LogDirName + '\';
LoadIni;
LoadRouteTable;
Log(Port_Modem + ' : ' + PortName_Modem);
Log(Port_AI + ' : ' + PortName_AI);
Log(Port_UI + ' : ' + PortName_UI);
ResampledToModem := TMemoryStream.Create;
RAWDataFromModem := TMemoryStream.Create;
InitComPorts;
InitSockets;
Self.OnCloseQuery := FormCloseQuery;
Skype := TSkype.Create(Self);
Skype.OnAttachmentStatus := SkypeAttachmentStatus;
Skype.OnCallStatus := SkypeCallStatus;
Skype.OnMessageStatus := SkypeMessageStatus;
Skype.Attach(Protocol, False);
LBDSystem := TLBDSystem.Create; // Инициализация нашего класса
LBDSystem.Busy := False;
LBDSystem.Direction:= 0;
LBDSystem.OnAfterChangeBusy := ChangeBusy;
end;
end;
Procedure Tfrm_main.Log(S: String);
Begin
case cbox_EventsMode.ItemIndex of
0 : begin
// Nothing
end;
1 : begin // Only write to log
Memo_Log.Lines.Add(DateTimeToStr(Now)+ ' ' + S);
end;
2: begin // Write to log and send to skype-account
Memo_Log.Lines.Add(DateTimeToStr(Now)+ ' ' + S);
if cbox_EventsTransferTo.Text <> '' then
Skype.SendMessage(cbox_EventsTransferTo.Text, 'Log Event: ' + #10 + DateTimeToStr(Now) + ' ' + S);
end;
3 : begin // Only send to skype-account
if cbox_EventsTransferTo.Text <> '' then
Skype.SendMessage(cbox_EventsTransferTo.Text, 'Log Event: ' + #10 + DateTimeToStr(Now) + ' ' + S);
end;
end;
End;
procedure Tfrm_main.Memo_LogChange(Sender: TObject);
begin
if Memo_Log.Lines.Count >= 500 then
begin
Memo_Log.Lines.SaveToFile(AppLogDirectory + GetFileNameFromDateTime(Now));
Memo_Log.Clear;
end;
end;
procedure Tfrm_main.pum_RefreshSkypeContactsClick(Sender: TObject);
begin
RefreshSkypeContacts;
end;
procedure Tfrm_main.pum_SaveAdjustmentsClick(Sender: TObject);
begin
SaveIni;
end;
procedure Tfrm_main.pum_SaveTableClick(Sender: TObject);
begin
SaveRouteTable;
end;
Procedure Tfrm_main.SaveIni;
var
Ini: Tinifile; // создаем переменную типа Tinifile
x : Integer;
begin
Ini:=TiniFile.Create(AppDirectory + IniFileName);
Ini.WriteBool ('System', 'Use skin', chk_useskin.Checked);
Ini.WriteBool ('System', 'Auto start', chk_autostart.Checked);
Ini.WriteBool ('System', 'Minimize on start', chk_startminimized.Checked);
Ini.WriteInteger('Modem', 'Network mode', cbox_ModemNetworkMode.ItemIndex);
Ini.WriteBool ('Modem', 'Boost audio stream', chk_BoostFromModem.Checked);
Ini.WriteBool ('Modem', 'Smooth audio stream', chk_SmoothFromModem.Checked);
Ini.WriteInteger('Modem', 'BufferSizeMultiplier', BuffSize div 320);
Ini.EraseSection('Admins');
//Ini.WriteInteger('Admins','Count',lbox_Admins.Items.Count-1);
if lbox_Admins.Count > 0 then
for x:=0 to lbox_Admins.Items.Count-1 do
Ini.WriteString ('Admins', lbox_Admins.Items[x], lbox_Admins.Items[x]);
Ini.WriteInteger('Incoming GSM', 'Mode', cbox_IncomingMode.ItemIndex);
Ini.WriteString ('Incoming GSM', 'Tranfer to', cbox_IncomingTransferTo.Text);
Ini.WriteInteger('Incoming SMS', 'Mode', cbox_IncomingSMSMode.ItemIndex);
Ini.WriteString ('Incoming SMS', 'Tranfer to', cbox_IncomingSMSTransferTo.Text);
Ini.WriteInteger('Events', 'Mode', cbox_EventsMode.ItemIndex);
Ini.WriteString ('Events', 'Tranfer to', cbox_EventsTransferTo.Text);
Ini.WriteString('Restrictions', 'Codes', edt_codes.Text);
Ini.WriteString('Restrictions', 'Min', edt_Min.Text);
Ini.WriteString('Restrictions', 'Max', edt_Max.Text);
Ini.WriteBool ('Restrictions', 'SMS follows', chk_SMSFollowToGSM.Checked);
Ini.WriteBool ('Safety', 'Use prefix', chk_UsePrefix.Checked);
Ini.WriteString('Safety', 'Prefix', edt_Prefix.Text);
Ini.WriteBool('Safety', 'Prefix enabled', edt_Prefix.Enabled);
Ini.Free;
end;
Procedure Tfrm_main.LoadIni;
var
Ini: Tinifile; // создаем переменную типа Tinifile
begin
Ini:=TiniFile.Create(AppDirectory + IniFileName);
chk_useskin.Checked := Ini.ReadBool('System', 'Use skin', True);
chk_autostart.Checked := Ini.ReadBool('System', 'Auto start', False);
chk_startminimized.Checked := Ini.ReadBool('System', 'Minimize on start', False);
cbox_ModemNetworkMode.ItemIndex := Ini.ReadInteger('Modem', 'Network mode', 0);
chk_BoostFromModem.Checked := Ini.ReadBool('Modem', 'Boost audio stream', True);
chk_SmoothFromModem.Checked := Ini.ReadBool('Modem', 'Smooth audio stream', True);
FromModemVolumeUp := chk_BoostFromModem.Checked;
FromModemSmooth := chk_SmoothFromModem.Checked;
BuffSize := GetBufferSizeValue(Ini.ReadInteger('Modem', 'BufferSizeMultiplier', 10));
BuffMicSize := BuffSize;
BuffSpkSize := BuffSize;
Ini.ReadSection('Admins', lbox_Admins.Items);
cbox_IncomingMode.ItemIndex := Ini.ReadInteger('Incoming GSM', 'Mode', 2);
cbox_IncomingTransferTo.Text := Ini.ReadString('Incoming GSM', 'Tranfer to', 'echo123');
cbox_IncomingSMSMode.ItemIndex := Ini.ReadInteger('Incoming SMS', 'Mode', 2);
cbox_IncomingSMSTransferTo.Text := Ini.ReadString('Incoming SMS', 'Tranfer to', 'echo123');
//cbox_EventsMode.ItemIndex := Ini.ReadInteger('Events', 'Mode', 1);
//cbox_EventsTransferTo.Text := Ini.ReadString('Events', 'Tranfer to', '');
edt_codes.Text := Ini.ReadString('Restrictions', 'Codes', '');
edt_Min.Text := Ini.ReadString('Restrictions', 'Min', '3');
edt_Max.Text := Ini.ReadString('Restrictions', 'Max', '15');
chk_SMSFollowToGSM.Checked := Ini.ReadBool('Restrictions', 'SMS follows', False);
chk_UsePrefix.Checked := Ini.ReadBool('Safety', 'Use prefix', False);
edt_Prefix.Text := Ini.ReadString('Safety', 'Prefix', '');
edt_Prefix.Enabled := Ini.ReadBool('Safety', 'Prefix enabled', False);
Ini.Free;
// cbox_IncomingMode.Items.
end;
end.