Asterisk, MeetMe, Zaptel, ZtDummy, Dahdi

A BigBlueButton-ös Fred Dixon nagyon jól összefoglalta, hogy mik a címben említett dolgok.

"We use Asterisk for the voice conferencing component, which enables us to allows us to mix incoming VoIP calls originate from within BigBlueButton and calls that come through the regular plain old wtelephone system. When running, Asterisk historically expects to have a special PCI card installed that would accept incoming signals from phone network (usually through a cable that looks like an Ethernet cable, but is actually a primary rate interface, which provides a maximum of 23 incoming lines and 1 data line). This PCI card also supplies a hardware timer that gives a consistent signal, say once every 100 milliseconds. Within Asterisk the default voice conferencing module is MeetMe. For whatever reason, MeetMe needs a timer to work. No timer, no voice conferencing. Over the years, there are Asterisk modules that provide a software timer (zaptel dummy or Dahdi), but both of these are Kernel modules, which require compilation against the kernel headers for the current linux setup.
The problem .... Unfortunately, package management systems (such as apt-get or rpm) don't support dynamic compiling of kernel modules. We can compile the module in the BigBlueButton VM (as you can see from the initial boot sequence), but not from within packages. This means, our goal of ultimately enabling anyone to install BigBlueButton with just a few commands, the primary command being
sudo apt-get install bigbluebutton
can't be reached using MeetMe. Currently, our install instructions using packages say "This installs everything except Asterisk, and for information how to do that, see these instructions." A recent thread on our forum that was over fifty messages long attests to the difficulty of setting up a kernel module. Also, many virtual host environments will not let the users install kernel modules (for obvious reasons), so it further restricts where developers can run BigBlueButton. We will still support MeetMe, but once we have support for App_Konference, we'll be able to update the packages and have BigBlueButton install on Ubuntu 9.04 with just a few commands. This means our developers need only spend a few minutes installing BigBlueButton and can focus more effort on integrating and extending BigBlueButton for the benefit of everyone."

Még annyit hozzá, hogy a Dahdi az az új neve a Zaptel-nek, valami jogi / copyright problémák állnak a háttérben.

OpenOffice dokumentumból szöveg kinyerése

Ismét .NET

Most éppen megnyitott OpenOffice dokumentumból kell kiszedni a szöveget. A letöltött OpenOffice SDK-ból kell betenni a References-be az öt darab cli_*.dll -t. Aztán:


public class OpenOfficeReceiver : ITextReceiverInterface.ITextReceiver
{

private XTextDocument oDoc;

public void createDocument()
{
XComponentContext oStrap = uno.util.Bootstrap.bootstrap();
XMultiServiceFactory oServMan = (XMultiServiceFactory)oStrap.getServiceManager();
XComponentLoader oDesk = (XComponentLoader)oServMan.createInstance("com.sun.star.frame.Desktop");
string url = @"private:factory/swriter";
PropertyValue[] propVals = new PropertyValue[0];
oDoc = (XTextDocument)oDesk.loadComponentFromURL(url, "_blank", 0, propVals);
}

public String giveBackTheTextContent()
{
return oDoc.getText().getString();
}
}
Már megint egy bejegyzés, ami .NET-es és nem Java-s. Az alábbi kód a "Word" title-lel rendelkező alkalmazáson figyeli az Enter gomb lenyomását.


public class FilterLogic{

public delegate void filteredEvent();

private filteredEvent currentFilteredEvent;
private InfoDelegate infoDelegate;
private Logger logger;

public FilterLogic(InfoDelegate infoDelegate)
{
this.infoDelegate = infoDelegate;
this.logger = new Logger(infoDelegate, "FilterLogic");
}

public void setFilteredEvent(filteredEvent currentFilteredEvent){
this.currentFilteredEvent = currentFilteredEvent;

}



public void filterEnterAndApp(IntPtr a, ref Hook.KBDLLHOOKSTRUCT lParam)
{

//ENTER KEY
if (0X0D == lParam.vkCode)
{

try
{

IntPtr hwnd = APIFuncs.getforegroundWindow();
Int32 pid = APIFuncs.GetWindowProcessID(hwnd);
Process p = Process.GetProcessById(pid);
String appName = p.ProcessName;
String appltitle = APIFuncs.ActiveApplTitle().Trim().Replace("\0", "");
Console.WriteLine(appltitle);
if (appltitle != null && appltitle.Contains("Word"))
{
if (currentFilteredEvent != null)
{

currentFilteredEvent();

}
else
{
logger.logMsg(Logger.WARNINGTYPE, "there is no filteredEvent is set, so no function will be called.");

}
}

}
catch (Exception ex)
{
logger.logException(ex);
}
}
}
}


public static class Hook
{
//Similar class is on this site:
//http://blogs.msdn.com/toub/archive/2006/05/03/589423.aspx

private static class API
{

//dll imports for hooking and unhooking and sending events trough hook hierarchy

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(
int idHook,
HookDel lpfn,
IntPtr hMod,
uint dwThreadId);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(
IntPtr hhk);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(
IntPtr hhk,
int nCode,
IntPtr
wParam,
//IntPtr lParam);
ref KBDLLHOOKSTRUCT lParam);

[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(
string lpModuleName);

}

public struct KBDLLHOOKSTRUCT
{
public int vkCode;
int scanCode;
public int flags;
int time;
int dwExtraInfo;
}

public delegate IntPtr HookDel(
int nCode,
IntPtr wParam,
ref KBDLLHOOKSTRUCT lParam);

public delegate void KeyHandler(
IntPtr wParam,
ref KBDLLHOOKSTRUCT lParam);

private static IntPtr hhk = IntPtr.Zero;
private static HookDel hd;
private static KeyHandler kh;

//Creation of the hook
public static void CreateHook(KeyHandler _kh)
{
Console.WriteLine("CreateHook _kh: " + _kh);
Process _this = Process.GetCurrentProcess();
ProcessModule mod = _this.MainModule;
hd = HookFunc;
kh = _kh;

hhk = API.SetWindowsHookEx(13, hd, API.GetModuleHandle(mod.ModuleName), 0);
//13 is the parameter specifying that we're gonna do a low-level keyboard hook
//Console.WriteLine(Marshal.GetLastWin32Error().ToString());
//MessageBox.Show(Marshal.GetLastWin32Error().ToString()); //for debugging
//Note that this could be a Console.WriteLine(), as well. I just happened
//to be debugging this in a Windows Application
}

public static bool DestroyHook()
{
//to be called when we're done with the hook

return API.UnhookWindowsHookEx(hhk);
}

//called when key is active
private static IntPtr HookFunc(
int nCode,
IntPtr wParam,
ref KBDLLHOOKSTRUCT lParam)
{
//Console.WriteLine("nCode=" + nCode);
//Console.WriteLine("wParam=" + wParam);

int iwParam = wParam.ToInt32();
//depending on what you want to detect you can either detect keypressed or keyrealased also with a bit tweaking keyclicked.
if (nCode >= 0 && (iwParam == 0x100 ||
iwParam == 0x104)) //0x100 = WM_KEYDOWN, 0x104 = WM_SYSKEYDOWN
kh(wParam, ref lParam);

return API.CallNextHookEx(hhk, nCode, wParam, ref lParam);
}
}



class APIFuncs
{

#region Windows API Functions Declarations

//This Function is used to get Active Window Title...
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
public static extern int GetWindowText(IntPtr hwnd, string lpString, int cch);

//This Function is used to get Handle for Active Window...
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern IntPtr GetForegroundWindow();

//This Function is used to get Active process ID...
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern Int32 GetWindowThreadProcessId(IntPtr hWnd, out Int32 lpdwProcessId);

#endregion

#region User-defined Functions

public static Int32 GetWindowProcessID(IntPtr hwnd)
{
//This Function is used to get Active process ID...
Int32 pid;
GetWindowThreadProcessId(hwnd, out pid);
return pid;
}

public static IntPtr getforegroundWindow()
{
//This method is used to get Handle for Active Window using GetForegroundWindow() method present in user32.dll
return GetForegroundWindow();
}

public static string ActiveApplTitle()
{
//This method is used to get active application's title using GetWindowText() method present in user32.dll
IntPtr hwnd = getforegroundWindow();
if (hwnd.Equals(IntPtr.Zero)) return "";
string lpText = new string((char)0, 100);
int intLength = GetWindowText(hwnd, lpText, lpText.Length);
if ((intLength <= 0) || (intLength > lpText.Length)) return "unknown";
return lpText.Trim();
}

#endregion
}

A loggertől és az infoDelegate-től tekintsünk el, mindkettő csak a logolást segítette. Beregisztrálni és leregisztrálni a keylistenert a kódban, ahol ezt meg akarjuk tenni, a következőképp lehet:


Hook.CreateHook(new Hook.KeyHandler(filterLogic.filterEnterAndApp));


Hook.DestroyHook();
Javabuzi meghasonulva

Bár javabuzi vagyok, vannak olyan feladatok, amikre nem a Java a legalkalmasabb. Mostanság több ilyen is adódott, kellett használni flex-et, grails-t, .NET-et is.

Tehát a probléma: szedjük ki bizonyos időközönként egy aktuálisan megnyitott dokumentumból a szöveget. C#.NET-et találtam a legkényelmesebbnek ehhez, bár így sem volt egyszerű. Rengeteg írás van a neten, hogy hogyan bizergáljunk lementett doc fájlokat, de ritka, hogy hogyan dolgozzunk egy aktuálisan megnyitott doksival. Annyi könnyíti a helyzetemet, hogy magát a dokumentumot az elején feldobhatom én is, így nem kell kikeresnem az aktívot, hanem feltételezhetem, hogy az általam megnyitottba írnak majd. Csupán a Microsoft.Office.Core és a Microsoft.Office.Interop.Word dll-eket kell csak behúzni. A kód valami ilyesmi, persze még az ütemes giveBackTheText() hívások kellenek köré:

public class WordTextReceiver
{

private Microsoft.Office.Interop.Word.Application wordApp;
private Document doc;


public void init()
{
createWordDocument();
}

private void createWordDocument()
{
wordApp = new Microsoft.Office.Interop.Word.Application();

object readOnly = false;
object isVisible = true;

// Here is the way to handle parameters you don't care about in .NET
object missing = System.Reflection.Missing.Value;
wordApp.Visible = true;

try
{
doc = wordApp.Documents.Add(ref missing, ref missing, ref missing, ref isVisible);

}
catch (COMException ce)
{
// some logging or error handling here
}

doc.Activate();
}


public String giveBackTheText()
{
return doc.Content.Text;
}
}
Szintakszis szinezés (vagy kiemelés?)

Nem igazán értettem eddig, hogy milyen problémás dolog tud lenni egy kódot szépen csicsázva publikálni egy blogon. Ez tipikusan olyasvalami, mely felett átsiklik az ember, elintézi annyival magában, hogy ODA KELL KOPIPÉSZTELNI, OSZT KÉSZENVAN. De ha egy kicsit is eltűnődsz, nem is oly egyszerű. Lehetőség lenne, hogy magadnál átfuttasd a kódodat egy html+css csicsázó készüléken, és az outputot kopizod a blogbejegyzésedbe. Ez nehezen módosítható utólag, béna megoldás.


Az ultimate megoldást egy sörivó srác adja (azért kér donation-t, hogy sört vehessen), itten van az oldala: http://alexgorbatchev.com/wiki/SyntaxHighlighter. Itt meg egy srác blogja, aki leírja, hogy ezt hogy is kell használni bloggeren: http://blog.cartercole.com/2009/10/awesome-syntax-highlighting-made-easy.html.


Röviden annyi a trükk, hogy javascript+css kombóval csinálja a syntax highlight-ot, magyarul runtime az oldal betöltésekor csicsáz, így a forrásban szépen módosítható marad a kód, cserélhető a stílus. A javascript kód ingyenes hosztolása is megoldott (mivel ugye bloggerre nemnagyon tehetsz fel ilyet).



Itt egy példa a script-es beillesztésre:




Itt meg egy a pre-s beillesztésre:



public class Allat{
private String str = "";
}


Különbséget nem látok, az indentálás mindkettőnél megmaradt, mindenesetre a pre-s rövidebb. Ja, és valami swf-es trükkel megcsinálták a kopipésztelhetőséget is, bár én nyomát sem találom flashnek, pedig SZÉTJOBBKLIKKELTEM az egész kódrészt... Szórszkódba meg nincs kedvem belenézni, működik és kész, ez az, amit szeretek.

UPDATE: mégis megtaláltam a flasht... nem eléggé SZÉTJOBBKLIKKELTEM előbb.

Licensz választás

Őrjítő dolog (angol) jogi szöveget olvasni egy programozónak.

És hihetetlen, hogy nem találtam normális for dummies stílusú leírást sem. Pedig most rákényszerültem, hogy körbenézzek ebben a témában. Akarok/akarunk indítani egy opensource projektet, nem akarom korlátozni a felhasználóit, hogy arra használják, amire csak akarják... ingyen, és anélkül, hogy nekik openszórsszá kelljen tenniük a fejlesztéseiket (nem teljesen szívjóságból, hiszen a projektet majd mi is természetesen üzleti célokra szeretnénk felhasználni, márpedig a kiegészülő részek openszórsszá tétele nélkül). Másik oldalról persze már szeretnénk mi is több kész komponenst is használni, tehát ezekkel is kompatibilis kell legyen a kiválasztott licensz. A szituáció adott, a választék is adott, van GPL (mindenféle verzióban), van LGPL (v3), BSD, CC.
Először azt hittem, hogy a http://www.gnu.hu segítséget nyújt, hisz legalább magyar. Tévedtem. Ez nem magyar, hanem egy senki által nem beszélt nyelv. Inkább visszatértem az angol leírásokra. Két értelmesebb oldalt találtam csak. Az egyik a Java viszonylatában magyarázza el az LGPL v2.1 -et, ami nyilván nagyon hasonlít a v3-ra: http://www.gnu.org/licenses/lgpl-java.html. Másik az egy magyar fórumbeszélgetés a CC és az LGPL közti különbségekről, megvilágítva az LGPL egyes elemeit: http://weblabor.hu/forumok/temak/19865.
A maradék licenszeket az eredeti angol leírásból próbáltam megértegetni, de már az elején sejtettem, hogy a GPL túl szigorú a felhasználást illetően, a BSD viszont túl engedékeny, hogy én ügyesen felhasználgathassak erősebb megkötésű komponenseket.
Marad az LGPLv3, míg jobbat nem találunk ki... Feladat kipipálva.

Google AppEngine #1 - Regisztrálás a rendszerbe

<for dummies style>
  1. Klatty a jobb felső sarokban szereplő "Sign up" linkre itt: http://code.google.com/appengine/
  2. Ország (Hungary = "not listed") és telefonszám megadása.
  3. Sms egy mp-en belül megérkezik a regisztrációs számmal, amit be kell írni itt egy textboxba.
  4. <nev>.appspot.com kiválasztása (6 és 30 karakter közötti hosszúságú és természetesen még le nem foglalt kell legyen); alkalmazás nevének beírása (sztem ez csak az adminisztrációs felületeken megjelenő név); engedjük-e bármely google accounttal történő bejelentkezést - alapból igen és nem néztem, hogy mit lehet még.
  5. Ordas beleegyezés mindenbe, google eladhatja a rokonaidat tevefarmra is innentől... szokásos.
</for dummies style>

Félreértés ne essék, magamnak írom for dummies stílusban. Később jól jön. Tapasztalat.
Kiderült. Nem tudom tovább titkolni. Java buzi lettem. Magamnak írom a blogot, nem másnak, így ne is nagyon legyenek elvárásaid. Azvan, hogy elértem agyi kapacitásom határát, így minden új információ kilök egy másikat. Arra kell ez a szájt, hogy feljegyezzem, amit egyszer már tudtam. Na elég.
top