2004年12月09日

1. event:

  private static readonly object DockStateChangedEvent = new object();
  [LocalizedCategory("Category.PropertyChanged")]
  [LocalizedDescription("Pane.DockStateChanged.Description")]
  public event EventHandler DockStateChanged
  {
   add { Events.AddHandler(DockStateChangedEvent, value); }
   remove { Events.RemoveHandler(DockStateChangedEvent, value); }
  }
  protected virtual void OnDockStateChanged(EventArgs e)
  {
   EventHandler handler = (EventHandler)Events[DockStateChangedEvent];
   if (handler != null)
    handler(this, e);
  }


2.   public new void Activate()
  {
        // what’s the new for?
  }

2004年12月05日

in the last post I used

           [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxDataLen)]
            public string data;

now I changed to using

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = MaxDataLen)]
            public char[] data;

this is closer to the C prototype. The string version would result in loss of the last character.

please see http://blogs.msdn.com/adam_nathan/archive/2003/05/09/56678.aspx for more infomration about the diff of the two methods.

关键的问题是如何传递 struct, which is defined in the usbid.h as:

typedef struct{
 int  Result;
 char ptrData[MaxDataLen]; 
 }DATASTR;
typedef struct {
 int  Type;  // Type of Event
 int  Channel;  // Channel
 //union EDATA
 DATASTR data;
}TV_Event; 


我这次的实验把两个 struct “拉平” 在一个 class 里面:
        [StructLayout(LayoutKind.Sequential)]
        class PhoneEvent
        {
            public Int32 type;
            public Int32 channel;
            //public DATASTR eventData;
            public Int32 result;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxDataLen)]
            public string data;
        }

注意为了接收返回字符串的值 我用了:
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxDataLen)]
            public string data;
在非struct 中一般用 StringBuilder 来获得返回值, 但是 struct 中不能使用 StringBuilder.


获得事件的C函数原型定义为:

int  TELMATEFUNC TV_GetEvent(int ch,TV_Event *event);

C# 中则被定义为:

        [DllImport("Usbid.dll")]
        static extern Int32 TV_GetEvent(UInt32 any, [Out] PhoneEvent phoneEvent);

[Out] 是我不经意中发现的,而正是这一发现解决了让我困惑的 得不到任何返回值的 问题。Yummy!


这是version 0.1 全代码:


—–
#region Using directives


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;


#endregion



namespace TeleMate
{
    public class Phone
    {
        PhoneEvent tvEvent;


        /// <summary>
    /// todo: add thread to poll events
    /// add metyhods for all the actions
    /// added event for all the concerned events
    ///
    /// </summary>
        public Phone()
        {
//            DATASTR dataStr = new DATASTR();
//            dataStr.data = new StringBuilder(MaxDataLen);


            tvEvent = new PhoneEvent();
//            tvEvent.eventData = dataStr;
            tvEvent.type = 100;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < MaxDataLen; i++)
            {
                sb.Append(” “);
            }
            tvEvent.data = sb.ToString();


        }


        public const int MAX_CALLINGID_LEN = 24;
        public const int  MAX_PLAYBUFSIZE = 4800;
        public const int  MAX_PLAYTOTALSIZE = MAX_PLAYBUFSIZE-1;


        public const int  CT_INTERNAL = 0; /* Internal channel */
        public const int  CT_EXTERNAL = 1; /* External channel */


        /****************************system event ***********************************/
        public const int  TEvent_InterOffHook  =  0; // 本地话机摘机事件
        public const int  TEvent_Ring= 3;   // 某一外线通道振铃事件
        public const int  TEvent_DialEnd =4;  // 拨号结束事件
        public const int  TEvent_PlayEnd  = 5;  // 放音结束事件
        public const int  TEvent_GetChar =  10;  // 收到DTMF码事件
        public const int  TEvent_OffHook = 11;  // 拨号后,被叫方摘机事件
        public const int  TEvent_HangUp =12;  // 挂机事件(必须调用设置忙音信号类型及忙音个数,方可产生该事件)
        public const int  TEvent_Nobody =13;  // 拨号后,没人接事件
        public const int  TEvent_Busy =14;  // 检测到忙音事件
        public const int  TEvent_InterHangUp = 19;    // 本地话机挂机
        public const int  TEvent_MicIn=26;           //麦克风插入事件
        public const int  TEvent_MicOut = 27;        // mic out
        public const int  TEvent_Dial = 28;          // dialtone detected
        public const int  TEvent_GetInterChar= 29;   // DTMF code pressed
        public const int  TEvent_GetFsk =30;        // get caller ID
        public const int  TEvent_GetDTMF=32;         // get caller id??
        public const int  TEvent_TelCallOut = 33;    // local phone out, the ring back signal detected after dial
        public const int  TEvent_SpkIn = 34;         // headphone plugged in
        public const int  TEvent_SpkOut =35;        // headphone out


    //—————————ERRORs————
        public const int  E_OK = 0×00;             /* OK */
        public const int  E_OUT_OF_MEMORY = 0×1;
        public const int  MaxDataLen=46;


        private bool isInit;


        [StructLayout(LayoutKind.Sequential)]
        class DATASTR {
            public Int32 result;
            public StringBuilder data;
        }


        /// <summary>
        /// to rep the PhoneEvent struct
        ///
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        class PhoneEvent
        {
            public Int32 type;
            public Int32 channel;
            //public DATASTR eventData;
            public Int32 result;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxDataLen)]
            public string data;
        }


        [DllImport("Usbid.dll")]
        static extern Int32 TV_GetEvent(UInt32 any, [Out] PhoneEvent phoneEvent);


        [DllImport("Usbid.dll")]
        static extern Int32 TV_Initialize();
       
        [DllImport("Usbid.dll")]
        static extern Int32 TV_Disable();


        [DllImport("Usbid.dll")]
        static extern Int32 TV_ReInit();


        [DllImport("Usbid.dll")]
        static extern void TV_EnableTel(bool enable);


        [DllImport("Usbid.dll")]
        static extern bool TV_IsTelEnable();


        [DllImport("Usbid.dll")]
        static extern bool TV_GetSerial(StringBuilder sb);


        [DllImport("Usbid.dll")]
        static extern bool VS_SetSigFreq(Int32 freq, Int32 freq1, Int32 freqID);


 


        public bool getEvent() {
            int result = TV_GetEvent(0, tvEvent);
            return  result == 1 ;
        }


        void ThreadProc() {
            while (!RequestStop) {
                System.Threading.Thread.Sleep(200);
                if (getEvent()) {
                    switch (tvEvent.type) {
                    case TEvent_GetFsk:
                            //Console.WriteLine(“GetFsk: ” + tvEvent.eventData.data.ToString());
                        Console.WriteLine(“GetFsk: ” + tvEvent.data.ToString());
                        break;
                    case TEvent_GetDTMF:
                            Console.WriteLine(“GetDTMF: ” + tvEvent.data.ToString());
                            break;
                    case TEvent_MicIn:
                        Console.WriteLine(“mic in”);
                        break;
                    case TEvent_MicOut:
                        Console.WriteLine(“mic out”);
                        break;
                    case TEvent_OffHook:
                        Console.WriteLine(“off hook”);
                        break;


                    case TEvent_Ring:
                        Console.WriteLine(“ring”);
                        break;
                    case TEvent_DialEnd:
                        Console.WriteLine(“dial end”);
                        break;
                    case TEvent_Busy://OK
                        Console.WriteLine(“busy”);
                        break;
                    case TEvent_PlayEnd:
                        Console.WriteLine(“play end”);
                        break;
                    case TEvent_HangUp:
                        Console.WriteLine(“hang up”);
                        break;
                    case TEvent_InterHangUp:
                        Console.WriteLine(“internal hang up”);
                        break;
                    case TEvent_InterOffHook:
                        Console.WriteLine(“internal off hook”);
                        break;
                    case TEvent_Nobody:
                        Console.WriteLine(“no answer”);
                        break;
                    case TEvent_GetChar:
                        Console.WriteLine(“get char: ” + tvEvent.data);
                        break;
                    case TEvent_GetInterChar:
                        Console.WriteLine(“get internal char: ” + tvEvent.data);
                        break;
                    case TEvent_TelCallOut:
                        Console.WriteLine(“call out”);
                        break;                               
                    default:
                        Console.WriteLine(“unknown type: ” + tvEvent.type);
                        break;
                    }
                }
            }
            _stopped = true;
            Console.WriteLine(“exit polling thread”);
        }


        bool _requestStop = false;
        bool _stopped = false;


        public bool RequestStop
        {
            get {return _requestStop;}
            set {_requestStop = value; }
        }
           


        public void Stop() {
            RequestStop = true;
            while (_stopped == false) {
                Thread.SpinWait(10);
            }
            Console.WriteLine(“disable device”);
            TV_Disable();
            isInit = false;
        }


        public void open() {
            if (isInit)
                return;
            else
            {
                VS_SetSigFreq(450, 0, 0);//设置两个最常见的单频(国内)频率(有部分国家使用双频)
                VS_SetSigFreq(437, 0, 1);//


                TV_Initialize();
                StringBuilder sb = new StringBuilder();
                TV_GetSerial(sb);
                Console.WriteLine(“a3 serial: ” + sb);
                new Thread(new ThreadStart(ThreadProc)).Start();
                isInit = true;
            }
        }
    }
}


 

2004年11月29日

again from
http://www.informit.com/guides/content.asp?g=dotnet&seqNum=106

summay:

1. for immutable string (IN parameter):  pass string objects direcly

2. for mutable strings (OUT params): using StringBuilder

e.g.

win32:

WORD GetConsoleTitle(
  LPTSTR lpConsoleTitle,  // address of buffer for title
  DWORD nSize             // size of the buffer
);

C#

[System.Runtime.InteropServices.DllImport("Kernel32.Dll")]
static extern UInt32 GetConsoleTitle(
  StringBuilder lpConsoleTitle,
  UInt32 nSize);

And I need to set the builder up properly:

StringBuilder sb = new StringBuilder(260);
UInt32 buffSize = (UInt32)sb.Capacity;
UInt32 titleLen = GetConsoleTitle(sb, buffSize);


from http://www.informit.com/guides/content.asp?g=dotnet&seqNum=105

The table below shows some of the more common Windows SDK types and their equivalent .NET Framework types.














































Windows SDK Type


.NET Type


BOOL


System.Boolean


DWORD


System.UInt32


LPDWORD


ref System.UInt32


HANDLE


System.IntPtr


LPHANDLE


ref System.IntPtr


HWND


System.IntPtr


LPCTSTR


System.String


LPTSTR


System.StringBuilder


LPWSTR


System.StringBuilder


TCHAR


System.Char


WCHAR


System.Char


UINT


System.UInt32


WORD


System.UInt16


2004年10月26日

I love JSF, so far.

I got my hands really dirty with JSF-Spring in the last few days trying to port the JPetStore demo app in the Spring distribution. Everything went really smooth until I decided to use the Acegi security framework to replace the security mechanism. It took me 2 days to have them integrated, because the Acegi stuff is out of faces domain and I needed to explicitly use the http session quite a bit to exchange information. All I can say is Sun RI 1.1.01 is quite stable and does almost everything by the textbook. The DI style of defining managed beans work really well with Spring, with the help of JSF-Spring library.

I have never liked Struts and Tapestry’s separation of web components from the HTML just adds one more layer of indirection that makes reading the “code” quite a bit of neuron activity. I have found I could read my JSF jsp pages faster than reading plain HTML or JSPs with with all those JSTL tags scatterd around.  The lession is: don’t mix JSF with other tag libs. JSF way is quite adequate for my little experiment.

The Creator thing as of this stage is good for learning JSF, and only for that purpose. Hand coding JSF is not any worse than coding JSP. Coding and debugging JSF in Tomcat with IDEA is as smooth as anything.  I still want to see how IBM Websphere Studio supports Drag’n Drop JSF development. Reading the redbook from IBM gave me the impression that IBM’s implementation could be a lot advanced than Sun’s Creator.

From now on I’ll recommend JSF to my clients.

 there’s going to be tons of jobs that require JSF in the near future.  –http://raibledesigns.com/page/rd/20041015#i_don_t_hate_jsf

 

 

the petstore facade is not serlizable because the DAO which uses rg.apache.commons.dbcp.BasicDataSource is not serializable. once the facade was injected into the a pge backing bean in the session scope, the session object can not be properly replicated in a clustered environment. Adding the “transient” keyword to the injected property may stop spitting the error message, but the replicated session bean will probably not function properly since the dependent business facade is not reinitialized.

 

 

2004年10月25日

added equality check to avoid excessive updating the authtication object with the container integration:

               if (newAuth != extracted) {  // br added to avoid reaplcing the new object
                    // Update container with new Authentication object (may have been updated during method invocation)
                    this.commitToContainer(request, newAuth);
                }
                else if (logger.isDebugEnabled()){
                    logger.debug(“auth not changed: ” + newAuth);
                }

To disable directory browsing, edit the file “web.xml” in Tomcat’s config directory.   Change the value of the parameter “listings” in the servlet named “default” from “true” to “false”.