Microsoft Lifecam Cinema Component for Windows Embedded Standard 2009
I'm aware that several people in the internet is also looking for a solution for that task. Well here it is: download the component design file (SLD) here. You can then simply import it to your component repository, and use it in your target design (search for "Lifecam" in the component list). Download the zipped folder that contains the Lifecam's driver here.
In your target design, don't forget to add the following components as well: PNP (User-Mode) and DirectShow Capture. I still have to analyze if they both should go into the SLD file.
I'm writing "from the ground up" document with topic: building a lean custom image of Windows Embedded Standard 2009 that supports Microsoft Lifecam Cinema. Stay tuned. Will have it ready this weekend. Cya! In the meantime, enjoy the music :) -- a composition by Collin McPhee (read this one as well) from his work Tabuh-Tabuhan.
UPDATE: here it is!
Microsoft Lifecam on Windows Embedded Standard 2009
Continuing DBConan Zeta....
I changed the implementation of the domain model of DBConan Zeta. In the previous entry I mentioned the domain object (Schema, Table, Column, etc.) will make use of QExplicitlySharedDataPointer. Well..., I decided this weekend to use QSharedDataPointer instead. More on that later.
Second, on the trick to avoid that "field has incomplete type". In the previous entry I said "use pointer". Now I decided to get rid of pointers altogether. It looks so un-QT-ish :) to me. I might be wrong here..., but the * signs hurt my eyes :).
Oh no, I'm slowly becoming a QT zealot. It reminds me of my early days learning Java 12 years ago....Source code here: http://www.box.net/shared/8zt5p6u9vz
Ok, on the jump from QExplicitlySharedDataPointer to QSharedDataPointer. Why? At first I thought QExplicitySharedDataPointer is the way to go, because -- the way I understand it -- it practically gives the effect of "pass-by-reference", which is the default mode of Java / C#.
For those who are not familiar with QT: QSharedDataPointer means implicit sharing..., while QExplicitlySharedDataPointer means explicit sharing.
In practical terms, implicit sharing means: when you modify an object, from within a function (that gets passed in the object), the caller of the function -- the one that passed the object into the function -- will not see the change you made on that object. Surprise (!). The reason is, at the point a non-const function is invoked on that object, the sharing is automatically broken; a deep copy is made, which means that object now has its own set of data, so that any changes made by that function would not ripple (inadvertently) to other part(s) of the program.
Hmm..., actually I'm not very happy with the way I explain it :). So, please head over to the authoritative source (in QT ref.) instead.
Ok, sounds like implicit sharing is not-intuitive (at least for Java / C# programmers). In Java / C#, by default, we expect the change we made in an object to ripple through the program (and we do some tricks when we want otherwise).
Here, with implicit sharing, it's exactly the opposite. So, why not use explicit sharing instead? Well, in a few words: I found it hard to achieve consistency with explicit sharing, partly because my domain objects have member fields of types that use implicit sharing (e.g.: QString and QList). Mixing implicit sharing and explicit sharing, in my opinion, is not a good thing. It will only lead to confusion.
Ok, let's suppose the Schema object is explicitly shared. Suppose you pass that Schema to a function (xxxFunc). Inside the function you obtain the list of Tables that belong to the schema. Then, you append another instance of Table to that list. You would expect that change to be seen from the part where you invoke the xxxFunc. Chance is: that's not the case. Because QList is implicitly shared.
So..., I thought "I don't want to mess with that. Let's stick with one approach only, implicit sharing". The (only) problem, or I'd rather say "consequence", with that decision is...: it requires a shift in my way of thinking (in the rest of the program). I will have to keep in mind (everytime I pass an object to a function): it's a pass-by-value, it's a pass-by-value.
That may not be as bad as it sounds. I think it has something to do with immutability. I remember Joshua Bloch in his book (Effective Java) mentions "favor immutability". Maybe this pass-by-value will force us to lean ourselves more toward that principle. I don't know..., we'll see. I'll report back on that later.
In the meantime you can download the C++ source code. Compare it with dbconan_schema.py below (complete python source: here). You see, there are many checks -- that are available in the python version -- currently not implemented in the C++ port. I'll get to that later. Ciao!
UPDATE: I also decided to change the target database from Oracle to Postgre. The reason: I don't have time to (re)compile QT on my Ubuntu Linux in order to have the QT's Oracle SQLDriver. On the other hand, Postgre SQLDriver comes out of the box (when we install QT SDK from the repository).dbconan_schema.py
In the Python+Oracle version the program makes heavy use of Oracle Data Dictionary (that's how it learns the structure of the database).
The equivalent of it in Postgre is "information schema". Here are a few tables in the information_schema that I think will be useful for the program:
select * from information_schema.tables where table_schema = 'public' -- public is the default schema name
select * from information_schema.columns where table_name = 'table_a'
select * from information_schema.constraint_column_usage
select * from information_schema.key_column_usage
select * from information_schema.referential_constraints
select * from information_schema.constraint_table_usage
select * from information_schema.table_constraint
DBConan Zeta
Right now I’m porting DBConan to C++, specifically using the QT framework (version 4.5.3). I’ve never programmed in C++ before, so the problem I’m posting here actually is an (embarrassing) basic problem in C++: it doesn’t compile :), with error message “file f_primaryKey has incomplete type”. The source code of the domain model is available here (yes, as a devout OO programmer I always start with the domain model) :D.
For those who are experienced in C++, please help me identify what exactly is the problem. I did all I knew: I’ve forward-declared the class PrimaryKey (see the top of DomainModel.h). No luck.
UPDATE: Found why. Here is the fixed code (separate file, those interested -- including myself, for not getting into the same issue -- can compare it with the earlier version). In a few words, it's another wrinkle I just learned in C++: when you declare "PrimaryKey primaryKey;" as an instance variable of "Table", I guess the compiler will look for the empty-args constructor of PrimaryKey, somewhere in the code, before the declaration of class Table. Of course, in this case, the forward declaration of PrimaryKey doesn't help as it only declares the type, not the constructors. So, the solution: use pointer. So, instead of "PrimaryKey primaryKey;", try "PrimaryKey* p_primaryKey;". Another possible way out (I think): partial class..., but there's no such thing in C++ :). Keywords for google: +"field has incomplete type" C++Ok, why C++? Well, I’ve never programmed in C++, though I always wanted too. The original DBConan – the prototype – was writen in Python because I had to run it on a UNIX machine, on which I didn’t have permission to install Java…, python was my only choice. It turned out to be a good thing for me, I could appreciate python more.
Hope that helps (I also googled using that phrase, but I didn't really find a direct / specific answer). I figured out what I explained above by doing some quick experiments.
Then, as I already stated in the presentation, this DBConan will have to have a GUI. For usability, analytic functions (which would be really difficult to use without GUI), eye-candies, etc. I decided not to use Java (swing) simply because… I’ve done Java for too many years. I need some change :). I’ve heard that QT is one of the better GUI framework out there, and it’s in C++. I read the book on programming QT (3 years ago), I liked it, and finally now I have a good excuse to use it :).
One of my first concerns was: memory management. As I wrote in my earlier post, in my understanding, in (standard) C++ we have to worry about who is responsible for deleting objects created (e.g.: the calling functions? or the one got passed in the object?). I know there’s auto_ptr in standard C++, but since I’m in QT why don’t we use what QT provides (and work well with the rest of QT framework). So I skipped auto_ptr entirely and go straight to QSharedData and QSharedDataPointer. In my case I decided to use QExplicitlySharedDataPointer, since I think it’s the model that resembles most closely the model in Java / C# that I’m familiar with.
Ok, I’m thinking here, guys, especially uni students: if you are interested in building something useful, using QT, for your thesis maybe, why not consider working with me on this?Well, I found DBConan quite useful. In my previous project in Nextel Mexico, the vendor required us to include relevant snapshot of the database whenever we report an issue / finding. Initially I did it the “normal way” (during learning phase): I did the querying manually, hoping from one table to another, and stop when I think I’ve covered the required subset. I quickly realized it was a waste of my time, so I wrote DBConan that allowed me to “slurp” the data quickly. I think this can be used in other situations that involve working with large and complex database structure.
Please email me if you’re interested. Favor de escribirme si te interesa. Silahkan menyurati saya (email) jika anda tertarik. raka.angga@gmail.com. It has to be in QT 4.5.x.
My current flow of thinking (related to charging)
From there, try to understand why those parameters -- and relevant charging rules -- matter to them. That's the high-level objective.
Once we have a better / more solid idea about parameters & the charging rules, we can go backward, to identifying places in our application where we can / should tap those parameters from. The objective is to make the application "charging friendly". By that I mean, the design facilitates the need to provide the usage parameters asked by the charging system (supposedly owned by the telco operator).
After that, go forward again (to the middle). At that point we will have to verify if the data we have tapped from our application really is useful / usable. A test bed will be required. In this case, the test bed would a charging system, similar to the one(s) used by the telco operators. I will be looking into OpenRate soon.
Coming out of that we will have more confidence that we have more / sufficient knowledge to be able to deal with requests from the client (telco operator) for anything related to their charging requirements.
I'll post again once I have managed to try out OpenRate.
List of things I tend to forget how to do....
- Configuring DNS + SRV records for SIP.
- Using tcpdump (command line).
- Using sox to convert wav to gsm.
Right now I'm trying to get AG-Project's CDRTool working on a Debian. It works together with OpenSIPS. I will use it as a testbed for charging alternatives we're trying to come up with for our solution offering. We're heading toward Diameter-based solution (since Diameter is the thing recommended for IMS). However, we're still in search for an opensource / free diameter server component (specifically CDF), and we haven't found one. So, we'll use this CDRTool (together with OpenSIPS and it's Radius accounting module) as a temporary solution. Let's see if it works.
Now, first I need to get this OpenSIPs taking registration for a domain (e.g.: mytelco.net). For that I need to create SRV records, somewhere in the BIND configuration. Done that before, but already forgot how. Geez :). I hope this one would work: http://www.anders.com/cms/263 ... or this... http://sipx-wiki.calivia.com/index.php/DNS_Configuration
UPDATE: Ok, done. At least now my OpenSIPS handles registrations & requests for domain "mytelco.net". I put here screenshots and quick notes. They summarize a couple of things I learned from various resources on the web during the setup (useful for future reference).
(1) Get OpenSIPS installed. For basic usage (as simple forwarding proxy) it is pretty straightforward, just follow the instructions on this page: http://bit.ly/cgFNxy. I used version OpenSIPS 1.6.1 on Debian 5, by the way. Please note, there's a little error in that manual: the author mistyped the db password for user 'opensips'. The two GRANT lines at the end, they should've been like this:
GRANT ALL PRIVILEGES ON *.* TO opensips@localhost IDENTIFIED BY 'opensipsrw';(2) Install BIND9: apt-get install bind9
GRANT ALL PRIVILEGES ON *.* TO opensips@127.0.0.1 IDENTIFIED BY 'opensipsrw';
(3) Configure BIND9: create zone files (forward and reverse), register them (in named.conf.local), reload bind (/etc/init.d/bind9 reload). See picture:
Right after that, modify resolv.conf (so that your Debian use the local DNS you just configured), and verify. See picture:
One obvious caveat here: if you use use dynamic IP (as in my case), you will have to repeat doing those steps (in the two pictures above) everytime you restart your machine (change the IP in the bind conf, and re-edit the resolv.conf).
Link to pages I read for configuring this thing:
- http://mit.edu/sip/sip.edu/dns.shtml
- http://www.debian.org/doc/manuals/network-administrator/ch-bind.htm
- http://linux.justinhartman.com/DNS_Installation_and_Setup_using_BIND9
- http://sipx-wiki.calivia.com/index.php/DNS_Configuration
alias=mytelco.netThat's it, and finally start your OpenSIPS: /etc/init.d/opensips start
The modification for file #2, I learned it from http://advantia.ca/references/opensips-1.5/INSTALL . Prior to doing that, I always got error 483 (too many hops) when trying to register from my SIP phone. I guess putting that alias is a quick fix (hey it works!), I yet have to see the surprises though (hope there's none!).
Finally, here's the configuration on the client side (X-Lite 3.0 on MS-Windows):
Now, on to the ugli(er) part: getting CDRTool working. I did that once as well, partially, also, forgot how to do it.... I will post the result once I get it done. Documentation was really scarce and inaccurate :|.
Alright, no I'm going to create a copy of my Debian's virtual harddisk. Chau!
UPDATE: This is so dissapointing. I thought after a year the situation of OpenSIPS & CDRTool has improved. Nope. Install guide of CDRTool is still inaccurate. Furthermore, although the latest release of CDRTool seems to be built in 2010, the install manual is still linked to FreeRadius 1.1.3!!! The latest version of Freeradius we have in Debian repository is: 2.0.x. Worse, CDRTool install guide doesn't mention that fact (you'll notice it only if you open the readme of the patch it provides for freeradius).
Gee.... Ok, I think I should forget CDRTool. All I need from OpenSIPS is just the usage data, raw CDR as generated by the OpenSIPS (which I will feed in to a better, more professionally-documented rating engine). So, goodbye CDRTool, adios, chau chau. I really doubt the authors if the authors of CDRTool spent some efforts to make sure it's usable for ordinary people like me.
Right now I'm reading the manual for enabling radius accounting in OpenSIPS: http://www.opensips.org/Resources/DocsTutRadius ... Alas! found some typos (filename, section 3.2., they should have typed radiusclient.conf instead of radiusclient-ng.conf). Also, in that same section, I'm kind of stuck trying to figure out what line to put in /etc/freeradius/clients.conf. Why, oh, why can't they reach the level of Asterisk (I'm referring to availability of QUALITY manuals / references).
Cataroo Presentation – Part 2 – Test cases
Here it is, part 2 of the presentation about Cataroo. In this part I explain a couple of points related to defining test-cases for the sample application (callback). While I’m at it, I also touch a couple of relevant points about the design of the sample application. I believe, to excel, a Software Development Engineer in Test (SDET), just like his SDE counterpart, has to have a firm knowledge of software design. Without further ado, I hope you enjoy this part!
That stylistic figurine in the video-still is wayang (shadow puppet, a form of art spread throughout Asia. It flourishes especially in Java and Bali).
Just came to know a couple of days ago (from youtube) a very cool group based in the US that innovates on wayang, ShadowLight Productions. Thirty years perfecting the techniques, onward. That is dedication. I invite you to check out one of their works, Ambrosia of Immortality.
The short clips I used in my video are Punjabi songs I like a lot (for the beat & also for the dancing):
- Jind Mahi – Malkit Singh.
- Babe Bhangra Pounde Ne – Gurdas Mann.
Ok, back to tech topic :), just realized that this small series of presentations about Cataroo is actually what I had in mind for segment 2 of my IMS video-series.
Sharing: SIP-based call-recording application
The recording itself is achieved by dragging the contact-center agent and the customer into a dynamically-created conference room, and have a silent-participant in the room, taping the conversation.
It is a sub-optimal solution. A better one would be to use things like mediaproxy or rtpproxy (have the RTP streams in the call go through that proxy, and tap the packets right there). The reason we designed it that way -- using conference -- is because they wanted to make use of the media server (with support for conferencing) that they have bought.
The source code is opened now; should serve as an additional resource for you who just started SIP-application development. I don't have time at this moment to write a how-to deploy and run it, less the detail of the design & code.
I invite you to do it. If you'd like to take that invitation, please write me an email at raka.angga@gmail.com or you can simply drop a comment here. Your help on this will be greatly appreciated, and it would really help fellow engineers out there.
Cataroo presentation -- part one.
Just uploaded the first part of the presentation of Cataroo.
I already have the screen-recordings of the manual executions of the test-cases. I need to edit them to present of a single, coherent story. I still have to think about a couple of points to say especially in the design of the test-cases section and data analysis section. I might be able to post the narration for the second (hopefully final) part tonight.
In the meantime, I hope you find this one useful!
Update: Just uploaded another video in this series, part 2 of cataroo presentation.
Cataroo
UPDATE: The video is available in another blog entry.
UPDATE: The user manual of Automated Scenario-Test Descriptor is available in another blog entry.
At this very moment I'm making a video presentation of a test-tool I just made. It is a cross-breed between that bastard thing, and a great test framework named KitCAT (Kit for Converged Application Test).
What's cataroo, you might ask. Well, here's the story. First, I named it BastardizedCAT (from Bastard + KitCAT). But then I found the name a bit ugly (it doesn't sound funny). A lookup in dictionary gave me this:
bastardized adj. (Arts): deriving from more than one source or style. impure (vs. pure) --- (combined with extraneous elements) [WordNet 1.5].So, it's cross-breed, sort of. Coincidentally, when I was thinking of a better name, my cat was doing weird poses on my bed (please don't get me wrong). I was like: "Huh? Is that a kangaroo lying on my bed?". That's how the name cataroo came up (a cross-breed between cat and kangaroo).
Alright, here's the storyboard, with narration, of the presentation:
UPDATE: because I wouldn't be able to finish the video tonight, I decided to uploaded the scenario.xml (that contains the automation code) here. Look for it at the end of this posting. This is to give a sneak peek of what is to come....(1) What's the purpose of this presentation.
In this presentation I'm going to show a way we can automate the testing of converged application. As in my other presentations, I will still be talking about telephony application, specifically the ones that use SIP as the signaling protocol.
(2) What's the story line of this presentation.
Before we get to the point of crafting the automation of our tests, we certainly have to start with an understanding of what we will be testing. Therefore I'm going to start with an explanation of the application I use as the vehicle in this presentation. You can take it as a quick-briefing about the requirement of the application.
Then, based on the understanding, we will move on to defining the test cases. We are not going to go in depth here with the techniques of designing system test-cases for this kind of application. So, we will just settle with a couple of basic / normal use-case scenarios.
Once we have the test-case defined, we, ourselves, will have to run it. This activity is useful, obivously, to validate the test-case. We might learn that we have missed a couple of steps, made several wrong assumptions, etc. Related to the automation, one of the aspect we will have to learn / investigate by manually executing the test-case is the data. At the end of the day, I think, an application is about consuming, processing, and producing data. So, we want to make sure all the elements involved in the scenario that we are testing are producing and getting the correct data, which implies -- to some degree -- it processes the data correctly. Analyzing how the data is being processed, however, is another topic. We are not going to spend much time on it in this presentation.
Assuming that the test-case passed, our aim from learning the data is to know for a fact what constitute the "correct data". Of course, ideally, a major part of that knowledge should be obtainable from the requirement or design document. However, there is always a possibility that a couple of details are missing from those places. Hopefully we will be able to find out about it by manually executing the test-cases and doing data inspection.
So, in this presentation I will show you how to obtain the data (specifically the SIP messages), and how to relate them to the steps in the test-case.
Finally, we compile all that knowledge and transform them into the the automation code.
That would be it.
(3) Explain the application.
The application we will be testing is basically a SIP server that is capable of making a callback to someone (let's call it partyA) whenever someone else (partyB) is available. Here is the case:
There's a person Alice, who is very excited about an important business opportunity she just identified. She wants to tell her colleague, Bob, right away, on the phone. Bob was busy doing house chores. Being a responsible and honest person, he set his presence status to BUSY. The call from Alice, obviously, wouldn't get through.
Without this application, Alice would hear the ringing tone on her phone, which after 20-30 seconds would go away. No call is made. Alice, can retry later, of course, as long as she doesn't forget to do it.
With this application, Alice would be presented with an IVR that will ask her if she wants to be called back whenever Bob is available to take calls. Let's suppose Alice says "yes" (by pressing a key on her phone to indicate the choice). For Alice, it means one less thing to carry around in her head; "call bob, call bob later today". What a relief.
Now imagine Bob has finished washing the dishes, and ready to take calls. He will announce it on the web, saying "hey guys, I can to take calls now.". Well, for now, it actually will be as simple as picking AVAILABLE from the list statuses in a webpage that comes with the application, and specifying his SIP URI. [show screenshot].
At the very moment Bob makes that change, the application will establish a call with Alice, play an announcement to her ("Alice, we're going to connect you with Bob now. Please stay in line"), establish another call with Bob, and finally bridge the two calls, resulting in Alice and Bob talking to each other.
This application is a good vehicle for this presentations, because it has the following characteristics I'd like to show that we can write the automation for, using the tool I will present at the end of this presentation:
- It involves interaction with IVR, and there's a need to pass DTMF signal from a caller to the application. This is quite common in telephony applications, and we would like to know if the test tool we will be using allows us to do that, easily.
- It involves interaction using SIP (on the phone) as well as HTTP (using the web-browser). Furthermore, those two are interlinked. By that I mean an action performed during the call session (on the phone), will affect the state the application, and _that_ can be observed from the other side (the web browser). Vice versa. We _will_ see that the test tool allows us to automate the interaction from both sides.
(4) Explain a simple (basic / normal) test case
...
(5) Guide the audience through executing the test case manually
...
Also explain how to gather the data we need, and relate them to the steps in the test case.
...
(6) Guide the audience through crafting the automation
...
UPDATE: Date 25 Feb. 2010. Just uploaded the first part of Cataroo (video) presentation.scenario2.xml
Bastard (Big Automated Scenario-Test Active Runtime-Director)
UPDATE: The source code of bastard lib is now available http://www.box.net/shared/q0f90dmmx4
Anything goes just to have a nasty-sounding product name, eh? :D
Ok, so this entry is highly related to the previous entry where I post a documentation that explains (mostly) the format of the XML file in which you describe your test scenario. In this entry I'm posting the Java library I wrote that consumes the XML and runs the scenario. Download it from here: http://www.box.net/shared/nfns0u79k9 .
Well, it's not the library per se. Instead it's a little test project that uses the library. The library itself is included in that project (look for a file named bastard_api.jar in that ZIP; that's the library you would import into your project).
Alright, time for a quick explanation. Basically you will have to create a little program -- which I refer to as "Director" -- in order to use the Bastard API. It is typically very simple. Basically what it does are: (1) Loads the content of the XML file (whose name is passed in as an argument to the program execution). Then you (2) feed that XML string into a method named loadScenarioDef that belongs to the library class named ScenarioRunner. In return you will get an instance of ScenarioDefinition. Further you (3) create an instance of ScenarioRunner and spawn a thread to run it. There's an instance method named run that belongs to ScenarioRunner, into which you will have to pass the scenario definition you created in step 1 and the instance of mediator (see the doc in the previous entry to understand the meaning of it) .
Some screenshots...:
Step (1)
Step (2)
Step (3)
As you see in the screenshot of step 1, you will have to pass the path to the scenario XML file as the argument to the program execution. The project comes with several XML files that you can use to play with. Try duh.xml first (for its nice name). If you’re using Netbeans, use the following screenshot as a reference.
By running FrijolDirector with duh.xml, you should see this in the output console:
Okay. That’s all for today. Feel free to mail me in case you have trouble running / trying / using it. Saludos.