Atapi CallInfoChangeEvent not fired - c#

I am using the TAPI 2.0 wrapper from JulMar (https://atapi.codeplex.com/) and I'm having trouble with it.
The Initialization
void initTAPI()
{
myTAPI = new TapiManager("GetCaller");
if (!myTAPI.Initialize())
{
MessageBox.Show("FAILED!");
}else
{
name = myTAPI.Lines[0].Name;
lineName = (myTAPI != null && myTAPI.Lines.Length > 0 ? name : string.Empty);
foreach(TapiLine line in myTAPI.Lines)
{
line.NewCall += this.OnNewCall;
line.Ringing += this.OnRinging;
line.CallStateChanged += this.OnCallState;
line.CallInfoChanged += this.OnCallInfo;
}
MessageBox.Show(lineName);
}
}
So I get the lineName. When I now dial a number through the program, it fires
OnCallState
private void OnCallState(object sender, CallStateEventArgs e)
{
if (InvokeRequired == true)
{
this.BeginInvoke(new EventHandler<CallStateEventArgs>(this.OnCallState), new object[] { sender, e });
return;
}
label1.Text = "Outgoing Call...";
}
But what I actually want to do is to get the number of an incoming call, but OnCallInfo does not get fired.
OnCallInfo
private void OnCallInfo(object sender, CallInfoChangeEventArgs e)
{
if (InvokeRequired == true)
{
this.BeginInvoke(new EventHandler<CallInfoChangeEventArgs>(this.OnCallInfo), new object[] { sender, e });
return;
}
label1.Text = "Incoming Call...";
}
It says somehwere, that it only works with x86, so I changed the target but still no success.
PS: I have a call manager (ProCall) installed on the same machine, that tells me when someone calls, so I should be able to get the info in c# as well?
Here is the whole code if someone is interested: http://pastebin.com/Q5W5iGun

Depending on TSP, you may get call info messages, but TAPI does not force the driver to do this. So some TSP make you get the info yourself. In the Win32 API this is done via lineGetCallInfo.
After a quick look in this atapi wrapper, this happens in the GatherCallInfo method of the TapiCall class. However I can see no way to trigger this manually in this wrapper. You would need to modify the atapi source to make this a public method.

You can use example from TAPI which do the same. The only difference is new line.Monitor() method
foreach (TapiLine line in tapiManager.Lines)
{
try
{
line.NewCall += OnNewCall;
line.CallStateChanged += OnCallStateChanged;
line.CallInfoChanged += OnCallInfoChanged;
line.Monitor();
}
catch (TapiException ex)
{
LogError(ex.Message);
}
}
For further reading read this https://atapi.codeplex.com/SourceControl/latest#Atapi/trunk/source/test/TcMon/TapiMonitorForm.cs

Related

OpenSilver and Dispatcher.CheckAccess

I am working on porting an old Silverlight application over to OpenSilver. Throughout the Silverlight code there are if( <control>.CheckAccess())... to make sure to be on the correct thread. Is my impression this check is no longer needed in OpenSilver? In other words, the following Silverlight code can be transformed into the following:
Yes, I know that callback-based async methods have been replaced with awaitable tasks. I am going to ask some questions about that conversion in my next question, here. This question is exclusively about the fate of the Dispatcher.CheckAccess
Silverlight:
private void GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
cmc.getSlideImageCompleted += (s, e) =>
{
if (imageGrid.CheckAccess())
{
cmc_getSlideImageCompleted(s, e);
}
else
{
var args = new object[] { s, e };
imageGrid.Dispatcher.BeginInvoke(new getSlideImageCompletedDelegate(cmc_getSlideImageCompleted),
args);
}
};
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
}
to OpenSilver:
private void GetNextImage()
{
var cmc = ServiceFactories.CreateCartManager();
cmc.getSlideImageCompleted += (s, e) =>
{
cmc_getSlideImageCompleted(s, e);
};
var lastTime = SystemSettings.GetInstance().SlideShowData.LastImageTime;
cmc.getSlideImageAsync(string.IsNullOrEmpty(lastTime) ? null : lastTime);
}
There is no need to use Dispatcher.CheckAccess since OpenSilver is currently single threaded (it uses mono.wasm runtime which doesn't support threads yet).
However, OpenSilver keeps compatibility with Silverlight, so if you have an old Silverlight code which does the check you can just keep it (it will always return true when running in Browser).

how to make sure that function only fires once (RawInputEventArg)

I'm currently working on a method that gives the user the possibility to add a handscanner to a dicitionary in order to scan some barcodes with it. (before i started the scanners were hardcoded in the dictionary). my colleague from which i got this project, implemented the rawinput_dll in order to get all of the necessary data from the barcode scanner. The method to get the data is shown below:
private void OnKeyPressed(object sender, RawInputEventArg e)
{
if (!Scanners.ContainsKey(e.KeyPressEvent.DeviceName))
{
return;
}
else if (Scanners.ContainsKey(e.KeyPressEvent.DeviceName))
{
if (e.KeyPressEvent.KeyPressState == "MAKE")
{
return;
}
if (e.KeyPressEvent.VKeyName != "\n")
{
scanNumber += e.KeyPressEvent.VKeyName;
return;
}
devID = e.KeyPressEvent.DeviceName;
Debug.Print(devID);
Aufrufen(scanNumber);
scanNumber = "";
}
}
Basically there are three classes in this program (FrmMenu, FrmSettings and a Class for the Scanner itself). If you want to add settings for the program you click on a button that opens up a new instance of FrmSettings
private void BtnSettings_Click(object sender, EventArgs e)
{
FrmSettings settings = new FrmSettings();
settings.ShowDialog();
settings.BtnSave_Click(sender, e);
settings.Dispose();
}
In this form there 2 buttons where you can choose if you want to add a scanner that scans even numbers or one that scans odd ones. If you press one of the buttons you need to scan a barcode in order to get the information (VID of Scanner) which is used as key to add the new scanner to the dictionary.
private void OnKeyPressed(object sender, RawInputEventArg e)
{
if (newScanner == true)
{
devIDnew = e.KeyPressEvent.DeviceName;
scannerAnlegen(devIDnew);
}
}
scannerAnlegen is the methode that adds the scanner to the dict.
public void scannerAnlegen(string devIDnew)
{
if(EvenOrOdd == true)
{
Scanner ger = new Scanner("dev3", "even");
FrmMenu.Scanners.Add(devIDnew, ger);
newScanner = false;
}
else
{
Scanner ug = new Scanner("dev4", "odd");
FrmMenu.Scanners.Add(devIDnew, ug);
newScanner = false;
}
}
my problem rn is, that it seems like i cant get out of this OneKeyPressed method of the Settings class. the logic of the OneKeyPressed method of the FrmMenu Class is that it can only proceed if the scanner is in the dictionary. Adding the scanner seems to work because when i debug and try to add one scanner the second time it throws and exception and says something like "element with this key already added". But why does this code doesn't continue then?

Form not loading correctly

I'm trying to build a TAPI based phone call system using JulMar's Atapi x86. One of the functions is to pop a specific form on an inbound call. However, whenever the form pops, it comes up incorrect, as shown below (I have tried several forms as a test and they all do the same thing). There is no error, nothing in the output window to suggest what the issue is.
Code:
private void incomingcall(object sender, NewCallEventArgs e)
{
string phonenumber = e.Call.CallerId; //get the phone number of the call
SqlCommand getincoming = new SqlCommand(Querystrings.getincomingquery(), DB);
getincoming.Parameters.AddWithValue("##TELEPHONE", phonenumber);
DataTable results = new DataTable();
try
{
DB.Open();
using (var results = getincoming.ExecuteReader())
{
results.Load(results);
}
}
catch (Exception ex)
{
Inbound ib = new Inbound(phonenumber, null);
ib.Show();
}
finally
{
DB.Close();
}
if (results.Rows.Count == 1)
{
loadcontactrequest(Convert.ToInt32(results.Rows[0].ItemArray[0]), phonenumber);
}
else
{
loadinbound(phonenumber, results);
}
}
I have loaded these forms outside of this function at other points, meaning it is something to do with this function. Does anybody know where I'm going wrong?
EDIT:
private void loadcontactrequest(int ContactID, string phonenumber)
{
ContactRequest cr = new ContactRequest(ContactID, Global.loginbound("Single customer found", phonenumber));
cr.Show();
}
These functions have been tested elsewhere and work correctly individually, I believe it might be TAPI related.
EDIT 2 - Delegate:
public static void inittapi()
{
if (TestOptions.notapi)
return;
tapi = new TapiManager("Omitted");
tapi.Initialize();
foreach (TapiLine ad in tapi.Lines) //Get all lines available to this PC
{
if (ad.Name.ToUpper().Contains("Omitted"))
{
phoneline = ad;
phoneline.Open(MediaModes.All); //Open the phone line for making and receiving calls
phoneline.NewCall += new EventHandler<NewCallEventArgs>(new TAPI().incomingcall); //Add the incoming call event handler
}
}
}
It's possible that this event is triggered on a different thread than the UI thread of your application.
Modify the method like this to test whether this is the problem:
private void incomingcall(object sender, NewCallEventArgs e)
{
Form form;
if(Application.OpenForms.Count > 0)
{
form = Application.OpenForms[0];
}
if (form != null && form.InvokeRequired)
{
form.BeginInvoke(new Action(() => { incomingcall(sender, e); }));
return;
}
// Your current code goes here
}
This will identify that we are in a different thread than your main form (form) was created on and then execute the function again on the main form's thread.

Returning a value from C# function called using window.external.notify

I am making an app for windows phone 8 using phonegap.I called C# function from my javacript using window.external.Notify([commandname]).It calls the C# code correctly. But I want to return a string value from my C# code back to that javascript function.
For solution-
I tried using InvokeScript() method to call a javascript function and passed my result as a parameter to it. But it is giving me OutOfMemoryException.
My C# code is-
public MainPage()
{
InitializeComponent();
this.CordovaView.Loaded += CordovaView_Loaded;
CordovaView.Browser.ScriptNotify+=Browser_ScriptNotify;
}
private void Browser_ScriptNotify(object sender, NotifyEventArgs e)
{
string commandStr = e.Value.ToString();
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
//get the key data
if (commandStr == kToken + "-get" || commandStr == kMSISDN + "-get" || commandStr == kTermsAccepted + "-get" || commandStr == kUserDetails + "-get")
{
string[] keys = commandStr.Split('-');
key = keys[0];
if (!settings.Contains(key))
{
sampledata = null;
}
else
{
sampledata = (string)settings[key];
}
this.CordovaView.Browser.IsScriptEnabled = true;
this.CordovaView.Browser.InvokeScript("mydata", data);
}
else(commandStr == "removedata")
{
settings.Clear();
}
}
private void CordovaView_Loaded(object sender, RoutedEventArgs e)
{
this.CordovaView.Loaded -= CordovaView_Loaded;
}
}
}
Below is my javascript code-
function getDataForKey(key) {
window.external.Notify(key + '-get');
senddata: return data;
}
function mydata(inputdata)
{
alert(inputdata);
data = inputdata;
alert('Invoked script is running');
goto: senddata;
}
Please help me out on this. I am new to phonegap. So I am not able to understand how to call from javascript to C# and vice versa. I looked for a solution in phonegap documentation too,but to no relief.
Thanks in advance.
If you want to use PhoneGap/Cordova and do what you try to do in a platform independent way, cordova plugin mechanism is there to help. You should be implementing your own cordova plugin:
See Plugin Development Guide
And windows native side implementation details are here.

C# Workflow ManualWorkflowSchedulerService Multithreading Question

Hey guys, I just wanted to verify what I'm doing is correct. It came to our attention that a Windows Service had a pretty serious memory leak. I was able to track it down to how Workflow was being called. I reworked it a bit to stop the memory leak, but I wanted to validate that the code is doing what I think it is. Note I do not know the first thing about Workflow, so I'm coming to you.
Basically, the code was executing the Workflow on a thread, but was not removing the handler to WorkflowRuntime.Terminated. I am trying to ensure that the Workflow is executed asynchronously. Here are the relevant portions of code:
Checking to ensure there is only once instance of the WorkflowRuntime:
private static void _CheckRuntimeInstance()
{
lock (_padlock)
{
if (_wfRuntime == null)
{
_wfRuntime = new WorkflowRuntime();
ManualWorkflowSchedulerService schedulerService = new ManualWorkflowSchedulerService();
_wfRuntime.AddService(schedulerService);
_wfRuntime.StartRuntime();
}
}
}
Inside a static method, creating the specific WorkflowInstance to run:
_CheckRuntimeInstance();
// create the instance
WorkflowInstance instance = _wfRuntime.CreateWorkflow(typeof(WorkflowType),parameters);
instance.Start();
Guid instanceId = instance.InstanceId;
ThreadPool.QueueUserWorkItem(CallbackMethod, instanceId);
Thread callback method:
private static void DeviceLocationAssignmentCallback(Object state)
{
Guid instanceId = (Guid)state;
EventHandler<WorkflowTerminatedEventArgs> workflowTerminatedHandler = null;
EventHandler<WorkflowCompletedEventArgs> workflowCompletedHandler = null;
workflowTerminatedHandler = delegate(object sender, WorkflowTerminatedEventArgs e)
{
if (instanceId == e.WorkflowInstance.InstanceId)
{
// Remove event registration.
_wfRuntime.WorkflowTerminated -= workflowTerminatedHandler;
_wfRuntime.WorkflowCompleted -= workflowCompletedHandler;
if (e.Exception != null)
{
// Log error.
}
}
};
_wfRuntime.WorkflowTerminated += workflowTerminatedHandler;
workflowCompletedHandler = delegate(object sender, WorkflowCompletedEventArgs e)
{
if (instanceId == e.WorkflowInstance.InstanceId)
{
// Remove event registrations.
_wfRuntime.WorkflowTerminated -= workflowTerminatedHandler;
_wfRuntime.WorkflowCompleted -= workflowCompletedHandler;
}
};
_wfRuntime.WorkflowCompleted += workflowCompletedHandler;
_wfRuntime.GetService<ManualWorkflowSchedulerService>().RunWorkflow(instanceId);
}
EDIT: Changed the title of the post to get more views.

Categories

Resources