Frank Shearar SIP Component - delphi

I am looking at the demo program by Frank Shearar and cannot build the demo program. I fixed up all the references to "missing files" and the last errors that I am trying to fix are related to differences in the interface in classes and how they are used now...
Self.CalleeMedia := TIdSDPMultimediaSession.Create(Self.Profile);
vs
Self.CalleeMedia := TIdSDPMultimediaSession.Create(Self.Profile, ???, ???);
I know the interface now looks like....
constructor TIdSDPMultimediaSession.Create(Profile: TIdRTPProfile;
Factory: TIdSdpMediaStreamFactory; ExecutionContext: TIdTimerQueue);
and I could just add...
x := TIdSdpMediaStreamFactory.Create;
y := TIdTimerQueue.Create;
and pass these in? Or pas nil in both cases. There are a few other places where I get similar errors when building the demo program. Do I just need to create other objects that are required? If not, what additional steps are needed? Any assistance to get me started would be great.
Thanks,

I suspect I simply forgot to update the demo in line with the SDP API's interface!
Create the TIdSdpMediaStreamFactory and TIdTimerQueue before instantiating the TIdSDPMultimediaSession.
In particular, take a look at how the test case is set up, in test\TestIdSdp.pas:
procedure TestTIdSDPMultimediaSession.SetUp;
begin
inherited SetUp;
Self.Factory := TMockMediaStreamFactory.Create;
Self.Profile := TIdAudioVisualProfile.Create;
Self.Timer := TIdThreadedTimerQueue.Create(false);
Self.MS := TIdSDPMultimediaSession.Create(Self.Profile, Self.Factory, Self.Timer);
Self.PortBlocker := TIdMockRTPPeer.Create;
// We only instantiate Server so that we know that GStack points to an
// instantiated stack.
Self.Server := TIdUdpServer.Create(nil);
end;

Demo project can not be compiled. He has a lot of links to test* files. Also all the factory's was declared at the test project.

Related

Delphi - mORMot Can not access data through client using full memory model and TSQLRestClientURI

I've been trying to start a new project using mORMOt the DDD-way and have created a few classes and begun to test one of them in an easy/simple way.
I used the regression test code from your DDD-sample about TUser and modified it to suit my class .
I have tried to minimize the code and hopefully, it could contain some clues for you to help me understand what's wrong here.
I found that when only using the server, everything works ok but when using client the ORMselection won't find the data.
I stripped down the code as much as possible and marked with some comments where it works and where it not works.
class procedure TInfraRepoPackageFactory.RegressionTestsPackage(test: TSynTestCase);
procedure TestOne(Rest: TSQLRest);
var cmd: IDomPackageCommand;
qry: IDomPackageQuery;
package: TPackage;
begin
test.Check(Rest.Services.Resolve(IDomPackageCommand,cmd));
package := TPackage.Create;
try
package.articleNo := 10000;
test.check(cmd.Add(package)=cqrsSuccess);
end;
test.check(cmd.Commit=cqrsSuccess);
finally
package.Free;
end;
package := TPackage.Create;
try
test.Check(Rest.Services.Resolve(IDompackageQuery,qry));
test.Check(qry.SelectByArticleNo(10000,false)=cqrsSuccess); // <<-- Debugging shows that it will not find anything when using client.
test.Check(qry.GetCount=1); // <<-- getCount returns zero when using client.
end;
finally
package.Free;
end;
end;
var RestServer: TSQLRestServerFullMemory;
RestClient: TSQLRestClientURI;
begin
RestServer := TSQLRestServerFullMemory.CreateWithOwnModel([TSQLRecordPackage]);
try // first try directly on server side
RestServer.ServiceContainer.InjectResolver([TInfraRepoPackageFactory.Create(RestServer)],true);
TestOne(RestServer); // sub function will ensure that all I*Command are released // <<=== Works
finally
RestServer.Free;
end;
RestServer := TSQLRestServerFullMemory.CreateWithOwnModel([TSQLRecordPackage]);
try // then try from a client-server process
RestServer.ServiceContainer.InjectResolver([TInfraRepoPackageFactory.Create(RestServer)],true);
RestServer.ServiceDefine(TInfraRepoPackage,[IDomPackageCommand,IDomPackageQuery],sicClientDriven);
test.Check(RestServer.ExportServer);
RestClient := TSQLRestClientURIDll.Create(TSQLModel.Create([TSQLRecordPackage]),#URIRequest);
try
RestClient.Model.Owner := RestClient;
RestClient.ServiceDefine([IDomPackageCommand],sicClientDriven);
TestOne(RestServer); // <<=== Works
RestServer.DropDatabase;
USEFASTMM4ALLOC := true; // for slightly faster process
TestOne(RestClient); // <<=== DO NOT Work !!!!
finally
RestClient.Free;
end;
finally
RestServer.Free;
end;
end;
I also tried to put this question on the mORMot forum but the mailer can not reach the site.
Got this message :
An error was encountered
Error: Unable to send email. Please contact the forum administrator with the following error message reported by the SMTP server: "450 4.1.2: Recipient address rejected: Domain not found ".
I finally found what's wrong.
In the agregate, class TPackage, I had set the property of packageNo to "stored AS_UNIQUE" - that resulted in that the commit just stored zero in that field and then the SELECT('packageNo=?,[10001]) couldn't find anything.
I didn't realize that because the package object contained just 10001 and could never think of the possibility that the commit should store a 0.
But when I tested with TSQLHttpServer and TSQLHttpClient and a real database I could see all records containing zeroes in the packageNo field.
Then I understood that it must be something with this field that's wrong. When I looked up TPackage I found my mistake.
I should have set the "STORED AS_UNIQUE" in the TSQLRecordPackage class instead, the one that's used by ORM.
The moral of the story... "OPEN YOUR EYES.. and you will see" ;-)

How to get errors of the file using OTA?

I'd like to access the errors on the active file (.pas).
Now a days I can find it on the left side of the IDE, as you can see on image.
I found on OTA the interface IOTAModuleErrors, that seems to be what I want. But I didn't found it on BorlandIDEServices.QueryInterface or BorlandIDEServices.GetService. Someone knows how to access it ?
I found it!
It was much simpler than I thought, it's just a matter of casting the IOTAModule on the module to IOTAModuleErrors.
If you want a practical example you can check this project
I use on the unit Source/FindUnit.OTAUtils.pas, on function GetErrorListFromActiveModule.
Sample:
function GetErrorsListFromActiveModule: TOTAErrors;
var
ModuleServices: IOTAModuleServices;
ModuleErrors: IOTAModuleErrors;
begin
ModuleServices := BorlandIDEServices as IOTAModuleServices;
Assert(Assigned(ModuleServices));
ModuleErrors := ModuleServices.CurrentModule as IOTAModuleErrors;
Result := ModuleErrors.GetErrors(ModuleServices.CurrentModule.FileName);
end;
Thank you

DUnit Cannot create form. No MDI forms are currently active

Hey there i have a problem with my Unit Testing in Delphi XE3 i have a project that consist of 1 MDIForm and allot of MDIChild forms then problem is that when i run test on my MDIChild forms i get this error:
TestAllDataSrouces: EInvalidOperation
at $0064346F
SetUp FAILED: Cannot create form. No MDI forms are currently active
my Setup method looks like this:
procedure TestTCustomerCard.SetUp;
begin
FCustomerCard := TCustomerCard.Create(Application);
end;
what can i do to solve this error? so far i tried:
FCustomerCard := TCustomerCard.Create(Application.MainForm);
FCustomerCard := TCustomerCard.Create(nil);
And
procedure TestTCustomerCard.SetUp;
var
a : TForm;
begin
a := TForm.Create(nil);
a.FormStyle := fsMDIForm;
FCustomerCard := TCustomerCard.Create(a);
end;
and my test is:
procedure TestTCustomerCard.TestAllDataSrouces;
var
I: Integer;
begin
for I := 0 to FCustomerCard.ComponentCount-1 do
begin
if (FCustomerCard.Components[i] is TcxLookupComboBox) then
begin
Check(TcxLookupComboBox(FCustomerCard.Components[i]).Properties.ListSource = nil,'Error no ListSource, Lookup: '+TcxLookupComboBox(FCustomerCard.Components[i]).Name+' Parent: '+TcxLookupComboBox(FCustomerCard.Components[i]).Parent.Name);
end;
if (FCustomerCard.Components[i] is TcxDBTextEdit) then
begin
Check(TcxDBTextEdit(FCustomerCard.Components[i]).DataBinding.DataSource = nil,'Error No DataSet, Text Edit: '+TcxDBTextEdit(FCustomerCard.Components[i]).Name+' Parent: '+TcxDBTextEdit(FCustomerCard.Components[i]).Parent.Name);
end;
if (FCustomerCard.Components[i] is TcxGridDBTableView) then
begin
Check(TcxGridDBTableView(FCustomerCard.Components[i]).DataController.DataSource = nil,'Error no Data Source, DB Grid View: '+TcxGridDBTableView(FCustomerCard.Components[i]).Name);
end;
end;
end;
Demo Project: Here
What you are doing is more like a functional or integration test. You are checking that your UI is correctly set up. That kind of test is different from a unit test.
Unit tests are supposed to check that if you give a module certain inputs, then they produce certain outputs. Unit tests are localized. They are meant to test the behaviour of a unit independently from other units. A UI specifically depends on other units. They take data from input devices and operate on databases and on the whole have quite complicated set of dependencies. That makes them a bad target for unit testing.
Take a look at this question - Unit tests vs Functional tests
To do the kind of testing you want, it is probably best to make your own tool that can set up the environment correctly and perform the test.
The error message pinpoints the problem. If you need an MDI child form, it must have an MDI parent form. And that parent form must be the main form of your program. Hard to achieve in a DUnit project. Your solutions appear to be:
Make the main form of your program be an MDI main form. I think that will be tricky to achieve.
Make your form under test not be an MDI child form.
Find a way to test that does not require instantiation of this form.
I have encountered the same problem, and I decided to implement advice of David Heffernan and "Make your form under test not be an MDI child form".
Here I will describe how I could reach this. I have made all changes in my testcase unit.
Make test form that inherits original MDI child form
type TTestCustomerCard = class(TCustomerCard) end;
Add this just before your test case class.
Copy dfm file or the form, say CustomerCard.dfm, to TestCustomerCard.dfm
Open TestCustomerCard.dfm in any text editor, delete line
FormStyle = fsMDIChild (because fsNormal is default value),
change first line
object CustomerCard: TCustomerCard
to
object TestCustomerCard: TTestCustomerCard
Add directive
{$R TestCustomerCard.dfm }
In your SetUp method instead of
FCustomerCard := TCustomerCard.Create(Application);
write
FCustomerCard := TTestCustomerCard.CreateNew(Application);
InitComponentRes( 'TTESTCUSTOMERCARD', FCustomerCard );

Linking helpfile to an Delphi XE2 Application - everything works except main form

I'm working on getting the helpfile setup with our software. I have added HelpContext numbers for lots of specific forms/frame/controls and they all work fine. The problem is that the main form is not bringing up any help at all. For all of this I'm only using F1 to try to trigger the help.
I'm not at all an expert on Delphi or helpfiles, but I'll post what I've done and where I've looked.
Edit: Thanks to some help I now see the issue is due to the main form being a MDI parent. This still doesn't solve the problem.. it almost seems like a bug to me but I suppose it could be intentional for some reason. EndEdit
I'm including this unit: HtmlHelpViewer for the viewer. In the main forms Create constructor I've added the Application.Helpfile := 'asdf.chm'. For all the other forms I have just added context numbers and it's worked right away. I tried that on the main form and nothing happens. So I tried adding an Application.OnHelp event but this doesn't get called on the main form (and it does for all the other forms where help is working).
Last resort that I could think of was to trace deep down into the code and see what was happening. I got to TCustomForm.WMHelp in Vcl.Forms as the place where the split was happening. Said function has this loop:
if iContextType = HELPINFO_WINDOW then
begin
Control := FindControl(hItemHandle);
while (Control <> nil) and ( not ControlHasHelp(Control)) do
Control := Control.Parent;
if Control = nil then Exit;
GetHelpInfo(Control, HType, ContextID, Keyword);
Pt := Control.ClientToScreen(Point(0, 0));
end
When the main form was calling the Help Control would be nil and then it would exit. Anything else would go on fine.
I obviously don't know why this is happening. The answer could be something very basic. Any ideas would be appreciated!
According to your comments, the WM_HELP message is being targetted at your MDI client window. And since that is not a VCL control it does not respond to the WM_HELP message. You can deal with the problem by intercepting the message and asking the main form to handle it:
type
TMainForm = class(TForm)
protected
procedure WMHelp(var Message: TWMHelp); message WM_HELP;
end;
....
procedure TMainForm.WMHelp(var Message: TWMHelp);
begin
if (Message.HelpInfo.iContextType=HELPINFO_WINDOW)
and (Message.HelpInfo.hItemHandle=ClientHandle) then
Message.HelpInfo.hItemHandle := Handle;
inherited;
end;
If you want to be even more defensive you could write it like this:
if (Message.HelpInfo.iContextType=HELPINFO_WINDOW)
and (FindControl(Message.HelpInfo.hItemHandle)=nil) then
Message.HelpInfo.hItemHandle := Handle;
I've just had a look at my own MDI application and I can see that I have similar code to deal with this exact issue. If it hadn't been written over 10 years ago I might have remembered sooner!

Delphi - Form in DLL - Hints not showing

I have a Delphi form inside a DLL (I know that this restricts the use of the DLL to Delphi but this is not a problem in this case).
The DLL exports a function ShowForm that looks roughly like this:
procedure ShowForm (App : TApplication);
begin
OldApp := Application;
try
Application := App;
MyForm := TMyForm.Create (nil);
try
MyForm.ShowModal;
finally
FreeAndNil (MyForm);
end;
finally
Application := OldApp;
end;
end;
Now on the form I use a TAdvOfficeHint (from the TMS component pack). Unfortunately the hints do not show up.
Am I missing something here? How can I make the form behave exactly as it would if I showed it from the main application?
Thanks!
I don't know TAdvOfficeHint but I guess it hooks Application.OnShowHint to set its own THintWindowClass, and even if both the main executable and the DLL are linking in the TMS unit, they each have their own copy of the class which is where things go wrong.
Assigning Application is not enough: there are other global variables, like Screen, Mouse, etc. Others are even hidden in the implementation so I'd say your chances to make the form behave exactly as from the main application are slim.
Just found the reason why it does not work. As TOndrej states, TAdvOfficeHinthooks Application.OnShowHint and internally executes the following line of code:
FHintInfo.Assign (AHintInfo);
Assign internally uses a dynamic type check
if (Source is TAddvHintInfo) then ...
which fails due to the separate type registries of the DLL and the main application.
I have run into this problem a few times now and maybe I really have to switch to runtime packages to avoid all this stuff.
Anyway, if there's anything I can do to prevent this, please comment.
Wrong setting of Application.
Try this and see if it solves your problem:
procedure ShowForm (AppHandle : THandle);
begin
OldAppHandle := Application.Handle;
try
Application.Handle := AppHandle;
........
finally
Application.Handle := OldAppHandle;
end;
end;
I guess in Delphi 2006 and later versions you can call System.ShareMemoryManager method in the EXE code, so that its memory manager is shared with other modules loaded in the process memory space.

Resources