Phần 12: HelloPhone (bổ sung JMF)
Trong
chương 10 và 11, chúng ta đã sử dụng JAIN SIP kết nối 2 peer qua mạng
và JAIN SDP trao đổi các thông tin mà 2 peer sẽ thực hiện cuộc gọi.
Trong phần này, chúng ta sẽ bổ sung code JMF để thực hiện voice chat
giữa 2 peer, cũng như hoàn chỉnh phần mềm HelloPhone.
Chúng ta sẽ tạo 2 class:
- RingTool class : thực hiện tính năng:
+ Chơi nhạc chuông và dừng biểu diễn nhạc chuông.
- VoiceTool
class : thực hiện trao đổi voice chat giữa 2 peer. Class này giống hoàn
toàn ProcessVoiceChat class trong phần VII của chương 9. Bạn xem lại
chương 9 để hiểu code trong VoiceTool class.
I. RingTool class:
- Biến player : là đối tượng của class Player , để biểu diễn tập tin âm nhạc làm nhạc chuông.
- Phương thức startRing(String filename) : Chỉ ra vị trí và play tập tin âm nhạc .
- Phương thức stopRing() : Dừng play tập tin âm nhạc.
Lưu ý : Chúng ta đã biết rằng Player có 6 trạng thái Player có 6 trạng thái : Unreadlized, Realizing, Realized, Prefetching, Prefetched, Started.
Do đó, khi chúng ta gọi phương thức start() của player, player cần phải
có 1 khoảng thời gian đi qua 6 trạng thái đến trạng thái cuối cùng là
Started, player mới bắt đầu biểu diễn. Để tránh trường hợp khi player
chưa đi vào trạng thái Started mà chúng ta đã gọi phương thức stop() để
dừng player, điều này sẽ dẫn đến lỗi tê liệt chương trình. Do đó, trong
phương thức stopRing() , chúng tôi sử dụng đệ quy để xử lý khi player
chưa vào trạng thái Started thì không được gọi phương thức stop()
II. Cách hoạt động của RingTool trong HelloPhone:
a. Trường hợp biểu diễn RingTool:
-
Khi UAC bấm button YES và gởi đi thành công INVITE request, đối tượng
RingTool phía UAC chơi nhạc chuông để thông bao UAC đang gọi cho UAS.
-
Khi UAS nhận được INVITE request và gởi đi thành công "180 Ringing",
đối tượng RingTool phía UAS chơi nhạc chuông để thông báo UAS có cuộc
gọi từ UAC.
b. Trường hợp dừng RingTool: Có 3 trường hợp để dừng RingTool phía UAC và UAS.
- Trường hợp 1:
+ UAS bấm vào button YES để chấp nhận cuộc gọi và gởi đi "200 OK" thì RingTool phía UAS dừng nhạc chuông.
+ UAC nhận được "200 OK" thì RingTool phía UAC cũng dừng nhạc chuông.
- Trường hợp 2:
+ UAC bấm vào button NO để hủy cuộc gọi và gởi đi CANCEL request, thì RingTool phía UAC dừng nhạc chuông.
+ UAS nhận được CANCEL thì RingTool phía UAS cũng dừng nhạc chuông.
- Trường hợp 3:
+ UAS bấm vào button NO để từ chối cuộc gọi và gởi đi "486 Busy", thì RingTool phía UAS dừng nhạc chuông.
+ UAC nhận được "486 Busy " thì RingTool phía UAC cũng dừng nhạc chuông.
- Trường hợp 4:
+
Quá 30s mà UAS không thực hiện hiện bất cứ hành động nào thì HelloPhone
phía UAS tự động từ chối cuộc gọi, tương đương với hành động UAS bấm
vào button NO của trường hợp 3.
III. Thực hiện RingTool trong HelloPhone:
- Tập tin RingClient.mp2 sử dụng làm nhạc chuông phía UAC.
- Tập tin RingServer.mp2 sử dụng làm nhạc chuông phía UAS.
- Chúng ta sẽ tạo ra 2 đối tượng RingTool là biến toàn cục trong class HelloPhoneListener:
- Trong hàm dựng HelloPhoneListener(), chúng ta sẽ khởi tạo 2 đối tượng :
a. Trường hợp biểu diễn RingTool:
-
Khi UAC bấm button YES để gởi INVITE, đối tượng RingTool phía UAC chơi
nhạc chuông. Hành động này được thực hiện trong phương thức sendRequest() :
- Khi UAS nhận được INVITE request, đối tượng RingTool phía UAS chơi nhạc chuông Hành động này được thực hiện trong phương thức processRequest().
b. Trường hợp dừng RingTool:
- Trường hợp 1:
+
UAS bấm vào button YES để chấp nhận cuộc gọi và gởi đi "200 OK" thì
RingTool phía UAS dừng nhạc chuông. Hành động này được thực hiện trong
phương thức sendResponse().
+ UAC nhận được "200 OK" thì RingTool phía UAC cũng dừng nhạc chuông. Hành động này được thực hiện trong phương thức processResponse().
- Trường hợp 2:
+ UAC bấm vào button NO để hủy cuộc gọi, thì RingTool phía UAC dừng nhạc chuông. Hành động này được thực hiện trong phương thức terminateRequest().
+ UAS nhận được CANCEL thì RingTool phía UAS cũng dừng nhạc chuông. Hành động này được thực hiện trong phương thức processRequest().
- Trường hợp 3:
+ UAS bấm vào button NO để từ chối cuộc, thì RingTool phía UAS dừng nhạc chuông. Hành động này được thực hiện trong phương thức terminateResponse().
+ UAC nhận được "486 Busy" thì RingTool phía UAC cũng dừng nhạc chuông. Hành động này được thực hiện trong phương thức processResponse().
- Trường hợp 4: Quá
30s mà UAS không thực hiện hiện bất cứ hành động nào thì HelloPhone
phía UAS tự động từ chối cuộc gọi. Để thực hiện hành động này, chúng tôi
sử dụng java.util.TimerTask và java.util.Timer class.
+ java.util.Timer là class được sử dụng để lập lịch trình một luồng được thực thi ở một thời điểm nào đó trong tương lai.
+ java.util.TimerTask là abstract class kế thừa Runnable interface, nó định nghĩa một nhiệm vụ nào đó được lập lịch trong Timer class.
+ Định nghĩa một đối tượng Timer làm biến toàn cục:
+
Định nghĩa đối tượng TimerTask và khởi tạo timerS, khi UAS nhận được
INVITE request. Hành động này được thực hiện trong phương thức processRequest().
+
Chúng ta cũng phải loại bỏ lịch trình trong đối tượng timerS khi UAS có
hành động, bằng cách gọi phương thức cancel() của timerS. Dưới đây là
các trường hợp cần hủy lịch trình.
i1. Khi UAS chấp nhận cuộc gọi.
i2. Khi UAS từ chối cuộc gọi.
i3. Khi UAC hủy cuộc gọi.
IV. Cách hoạt động của VoiceTool trong HelloPhone:
Nhiệm vụ của VoiceTool :
+ Thực hiện cuộc gọi giữa 2 peer khi UAS chấp nhận cuộc gọi từ UAC.
+ Kết thúc cuộc gọi khi UAS hoặc UAC nhận được BYE request.
Dưới đây là hình ảnh miêu tả nhiệm vụ của VoiceTool trong quá trình thực hiện cuộc gọi giữa 2 peer.
* Quá trình bắt đầu cuộc gọi giữa 2 peer :
+ Bắt đầu từ UAS bấm vào button YES để chấp nhận cuộc gọi, VoiceTool phía UAS được bắt đầu.
+ VoiceTool phía UAC cũng bắt đầu cuộc gọi khi UAC nhận được "200 OK" response từ UAS.
* Quá trình kết thúc cuộc gọi giữa 2 peer : Có 2 trường hợp 2 xảy ra
- Trường hợp 1:
i. VoiceTool phía UAC sẽ dừng cuộc gọi khi UAC bấm vào button NO để kết thúc cuộc gọi.
ii. VoiceTool phía UAS cũng dừng cuộc gọi khi nhận được BYE request từ UAC.
- Trường hợp 1:
i. VoiceTool phía UAS sẽ dừng cuộc gọi khi UAS bấm vào button NO để kết thúc cuộc gọi.
ii. VoiceTool phía UAC cũng dừng cuộc gọi khi nhận được BYE request từ UAS.
V. Thực hiện VoiceTool trong HelloPhone:
- Tạo 2 đối tượng của VoiceTool class làm biến toàn cục:
- Trong hàm dựng HelloPhoneListener(…), chúng ta khởi tạo 2 đối tượng VoiceTool :
* Quá trình bắt đầu cuộc gọi giữa 2 peer :
+
Bắt đầu từ UAS bấm vào button YES để chấp nhận cuộc gọi, VoiceTool phía
UAS được bắt đầu. Hành động này được thực hiện trong phương thức sendResponse() :
+
VoiceTool phía UAC cũng bắt đầu cuộc gọi khi UAC nhận được "200 OK"
response từ UAS. Hành động này được thực hiện trong phương thức processResponse() :
* Quá trình kết thúc cuộc gọi giữa 2 peer : Có 2 trường hợp 2 xảy ra
- Trường hợp 1:
i.
VoiceTool phía UAS sẽ dừng cuộc gọi khi UAS bấm vào button NO để kết
thúc cuộc gọi. Hành động này được thực hiện trong phương thức terminateResponse() :
ii.
VoiceTool phía UAC cũng dừng cuộc gọi khi nhận được BYE request từ UAS.
Thông thường UAS chỉ gởi response đến UAC thôi, nhưng đây là 1 trường
hợp đặc biệt UAS gởi BYE request đến UAC. UAC nhận được BYE request cũng
trong phương thức processRequest() nhưng phía UAC. Những chương trước,
chúng tôi không nói đến vấn đề này, bởi BYE request phía UAC và UAS đều
thực hiện giống nhau. Nhưng trong trường hợp này, chúng ta phải xác định
BYE request này là của UAC hay UAS để sử dụng voiceClient hay
voiceServer dừng cuộc gọi. Do đó, Hành động này được thực hiện trong
phương thức processRequest(). Để phân biệt được BYE request này là do UAC hay UAS gởi, chúng ta dựa vào biến isUAS.
- Trường hợp 2:
i.
VoiceTool phía UAC sẽ dừng cuộc gọi khi UAC bấm vào button NO để kết
thúc cuộc gọi. Hành động này được thực hiện trong phương thức terminateRequest() :
ii. VoiceTool phía UAS cũng dừng cuộc gọi khi nhận được BYE request từ UAC. Hành động này được thực hiện trong phương thức processRequest() :
VI. Chạy chương trình :
Mỗi giao diện tương ứng 1 máy tính, nếu chạy trên cùng 1 máy tính port phải khác nhau.
Giả sử giao diện 1 :
- Port dành cho sip 6060, bấm vào button “Connect” để khởi động SIP.
- Port dành cho Voice là 40000.
- Destination là địa chỉ IP và Port của máy cần gởi đến.
- Bấm button “YES” để thực hiện voice chat.
Giao diện 2 :
- Port dành cho sip 6070, bấm vào button “Connect” để khởi động SIP.
- Port dành cho Voice là 50000.
- Destination là địa chỉ IP và Port của máy cần gởi đến.
- Bấm button “YES” để thực hiện voice chat.
Code đầy đủ :
http://www.mediafire.com/download/52xckdf7des8f7o/HelloPhone_JAINSIP.rar
RingClient.mp2 : http://www.mediafire.com/download/7d8ddf1vb3mo6k3/ringclient.mp2
RingServer.mp2 : http://www.mediafire.com/download/bchsm7z0p0e66fl/RingServer.mp2
Không có nhận xét nào:
Đăng nhận xét