안녕하세요, 타이젠 개발자 윤진입니다.


지난 한 달간 온오프믹스를 통해 Tizen Talks의 참가자를 받아왔습니다.

참고 : [Tizen Talks 2016 in Seoul] 타이젠 개발자 행사 참가자 2차 추가모집

생각보다 많은 분들께서 참석 의사를 밝히셔서 굉장히 놀랐습니다.


타이젠에 관심있는 대학생들 뿐만 아니라,

공기업, 대기업, 벤쳐기업 등 다양한 곳에서 근무하시는 분들이 참가신청을 해주셨습니다.

서울 뿐만 아니라 대구, 부산 등 지방에서 올라오시는 분들도 계시더군요.

관심을 가져주셔서 다시 한 번 감사합니다.


애초에 행사는 20~30명을 위해 기획되었지만,

인원모집 단계에서 총원을 100여명까지 늘렸습니다.

마음 같아서는 참가신청을 원하는 모든 분들을 받아들이고 싶었지만,

장소가 협소하여 어쩔 수 없이 온오프믹스 참가신청을 마감하였습니다.

현재 대기인원 포함 200여분이 등록을 하셨기에 대기등록도 어렵습니다.

참석을 원하는 분은 따로 알려주세요.


애초의 세션 발표안이 약간 수정되었습니다.

참가자를 모집하며 듣고 싶은 내용에 대한 정보를 수집하였는데요,

좀 더 깊이있게 그리고 폭넓게 파고 들어야 하는 세션은 다음으로 미루기로 결정하였고,

플랫폼 전체를 훑으며, 서로 유기적으로 연결되는 세션을 남겨두었습니다.



박영주, Application, "타이젠을 말하다."

이세문, Application Framework, "Tizen Application Inside Out"

정우현, UI Framework, "타이젠 UI앱의 필수, EFL 파헤치기"

문관경, Window system, "더 빠르고 더 유연한 윈도우 시스템(Wayland on Tizen 3.0)"

우상정, Kernel / System Framework, "바닥부터 만들어보는 Tizen"

윤  진, Native App, "타이젠 오픈소스의 커미터가 되어보자! "

이승환, SDK Plugins, "Tizen SDK를 이용한 Tizen Platform 개발"


이번 행사를 위해 어디에서도 들을 수 없는 내용을 준비하고 있습니다.

발표자 분들께서 한창 리허설을 하고 계실 수도 있겠네요.



권오훈, Service Framework, "타이젠 서비스 개발 공통기능 파헤치기"

김기동, Security, "더 안전해진 개인정보 관리"

강석현, Web App, "Javascript Is Eating The World"


상기 세 개 세션은 다음 TT때 찾아뵙도록 하겠습니다.

개인적으로 꼭 듣고 싶은 세션들이어서 아쉬움은 크지만,

일회성 행사가 아니기에 다음 TT를 기다려보기로 합니다.



이 행사는 개발자들이 직접 주관하는 행사입니다.

현업에서 코드를 짜고 있는 개발자들이 만든 행사이기에,

여러가지로 부족한 점이 많이 있습니다.


원래의 취지는 개발자들끼리 한 번 모여서 '우리끼리' 넋두리를 늘어놓아보자 정도인데요,

행사 참석자가 많아져서 그냥 넋두리만 늘어놨다가는 안될 것 같더군요.


그래서 개발자들이 코딩하다 말고 장보고 준비하여 다과를 마련하였습니다.

대단한 것은 아니나 귀엽게 봐주셨으면 좋겠습니다.


주차는 기본적으로 불가하나,

먼 지역에서 오신 분들에게는 예외적으로 주차하실 수 있도록 하겠습니다.

이 부분은 참석자분께서 받은 메일로 답변주시면 됩니다.


며칠 안남았네요.

날도 추운데 감기 조심 하시고 행사날 뵙겠습니다.

끝_

  1. 코코콩 2016.01.20 11:06 신고

    흐어어어... 참석하고싶으나........ㅠㅠ

    혹시 발표자료 올려주실수 있으신가요?

    • 안녕하세요~ 코코콩님.
      제가 만든 자료는 Tizen Talks 그룹 및 본 블로그에 올릴 예정이고,
      다른 발표자 분들의 자료는 Tizen Talks에 올리려고 합니다. :)



안녕하세요, 타이젠 개발자 윤진입니다.


얼마 전에 TT(Tizen Talks) 행사를 개최한다는 사실을 알려드렸는데요.

예상 외로 많은 분들이 관심을 가져주셔서 참가자 1차 모집을 마감하였습니다.

1차 모집 인원은 발표장 크기에 걸맞게 50명으로 책정했었지요.


비록 국내에 타이젠 모바일 제품이 출시되지 않았지만,

타이젠이 탑재된 기어시리즈가 널리 알려지고 있어서 10명만 와도 성공이라고 생각했었죠.


사실 발표자만 10명이 넘고,

행사운영으로도 그만한 숫자의 사람들이 투입이 되는데요,

행사를 준비하는 사람이 참가하는 사람보다 많아도 실망하지 말자고 다짐하고 있습니다.

(사실, 무명의 행사에 10명만 와도 성공이죠)


실제로는 얼마나 와주실지 아직도 걱정스럽기는 하지만,

그래도 참석의사를 밝히신 분이 50명이 넘었다는 사실에 감탄하고 있습니다.

그리고 대기자 명단에 올려서 참석의사를 적극적으로 피력하는 분도 계셨습니다.

타이젠 행사에 관심을 가져주는 모든 분께 진심으로 감사드립니다.


그래서 발표장을 좀 더 널직한 곳으로 변경하였습니다.

물론 현재까지 온오프믹스를 통해 신청의사를 밝히신 50분이 모두 오시진 못하겠지만,

백만분의 일의 확률로 모두 오실 수도 있을테니 참가자를 더 받으려면 공간을 넓혀야죠.


행사장소는 삼성전자 서초사옥 3층 그대로이지만,

3층에 있는 가장 넓은 대강의장에서 진행하려 합니다.

총 백여명이 들어갈 수 있는 공간입니다.




사진 촬영 : 박문경 연구원님


물론 공간이 넓어진 만큼 부담스러운 마음도 생기긴 합니다.

좁은 곳에서 10명은 왠지 가득차 보이지만,

넓은 곳에서 10명은 굉장히 휑해보일테니까요;

그래서 공간을 넓히는 것에 대한 상당한 부담감이 있지만,

장소가 모자라는 것보다는 남는게 차라리 나을테니,

공간이 휑해서 오는 심리적 압박은 준비하는 쪽에서 스스로 이겨내기로 했습니다.


온오프믹스에 추가로 참가신청을 받을 수 있도록 인원을 늘려놓았습니다.

애초에 계획했던 50명에서 100명으로 2배 늘렸는데요,

50명이 가득차서 헛걸음 하셨던 분들은 다시 신청해주세요.



2차 추가모집으로 등록된 사람은 '15. 12. 25 기준으로 78명입니다.

참석자 100명에 추가 대기자 50명으로 설정해두었습니다.

만약 참석예정자 100명이 꽉찬다면 대기자로 등록해주세요.

참석예정자분들께 전화/문자로 참석여부를 확인한 후 대기자 분들을 추가로 확정할 예정입니다.

그러니 연락가능한 전화번호를 꼭 남겨주세요 :)

참석신청은 여기에서 하실 수 있습니다.

그리고 각종 문의는 TT 공식사이트에서 하실 수 있습니다.

https://www.facebook.com/groups/tizentalks/


끝으로 TT 행사 댓글을 하나 언급하고 싶습니다.

황보진원님께서 "(생략)... 가능성을 보고서 울산에서 서울까지... 가려합니다. 기회가 주어진다면 직접 가능성을 보고 같은 가능성을 보는 이들과 교류하고 싶습니다. 기대하고 있습니다."라고 댓글을 남겨주셨습니다.

행사를 준비하는 입장에서 여러가지를 고민하게 만드는 댓글입니다.

먼길 오시는 만큼 헛된 걸음으로 돌아가시지 않도록 열심히 준비하겠습니다.


그럼 즐거운 하루 보내세요~

끝_



  1. 타이젠... 2015.12.27 15:14

    타이젠의 발전을 애타게 기다리는 분들도 많습니다. 저는 아니지만 타이젠폰 해외에서 직구했다가 램관리도 안되는 등 운영체제의 기본부터 개선해야 한다먀 다음 업데이트를 기다린다는 분도 있습니다.. 빨리 발전하길 바랍니다.

    • 안녕하세요? 의견 감사드립니다! 타이젠 모바일에 메모리 관련 정책은 매번 진화하고 있는 것으로 알고 있습니다. 그 사이에 불편을 느끼셨다니 여러가지로 송구스럽네요. 의견 주신 것을 소홀히 하지 않고 차기 버전에 반영할 수 있도록 하겠습니다. 감사합니다.



안녕하세요, 타이젠 개발자 윤진입니다.


드.디.어.

서울에서 타이젠 플랫폼 개발자들과 소통하는 자리를 마련하였습니다.

타이젠 플랫폼의 다양한 측면을 엿보실 수 있는 좋은 기회입니다.


박영주, Application, "타이젠을 말하다."

이세문, Application Framework, "Tizen Application Inside Out"

박춘언, UI Framework, "타이젠 UI앱의 필수, EFL 파헤치기"

우상정, Kernel / System Framework, "바닥부터 만들어보는 Tizen(Tizen from Scratch)"

문관경, Window system, "더 빠르고 더 유연한 윈도우 시스템(Wayland on Tizen 3.0)"

권오훈, Service Framework, "타이젠 서비스 개발 공통기능 파헤치기"

김기동, Security, "더 안전해진 개인정보 관리"

이승환, SDK Plugins, "Plugin을 추가하여 나만의 SDK를 만들기"

강석현, Web App, "Javascript Is Eating The World"

윤  진, Native App, "타이젠 오픈소스의 커미터가 되어보자! "


1회 TT(Tizen Talks)에서는 타이젠 플랫폼을 전체적으로 조망해보고,

2회, 3회... TT에서는 주요 Framework 별로 살펴볼 예정입니다.

타이젠 플랫폼에 관심있으신 분들의 많은 참여 부탁드립니다.


Tizen Talks 공식 그룹 : https://www.facebook.com/groups/tizentalks/

Tizen Talks 2016 in Seoul 등록하기 : http://onoffmix.com/event/59258


그럼 행사날 뵙겠습니다.

윤진 드림.

  1. YOhoho 2015.12.17 01:49

    우와아아아 기대됩니다 신청완료!

  2. 2015.12.19 08:17

    비밀댓글입니다


안녕하세요, 타이젠 개발자 윤진입니다.


Tizen 개발자 사이트에 방문해 보면 개발에 참고할만한 자료들이 많습니다.

말로만 좋다고 해봐야 입에 발린 소리를 하는 것으로 비춰질지도 모르니,

이번 포스팅은 철저히 Tizen 개발자 사이트의 자료를 이용하도록 하겠습니다.



여기에 들어가보시면 상기 그림과 같은 드럼앱 작성법이 나와 있습니다.

드럼을 치면 그에 맞는 소리가 플레이되는 간단한 앱입니다.

위의 그림만 봐도 드럼앱을 개발하고 싶은 욕구가 솟아나오시지요? :)


소리를 재생하려면 Player API를 사용합니다.

Player는 다수의 API로 구성되어 있는데,

그 중 라이프 사이클과 관련된 함수가 가장 중요합니다.

- player_create(), player_destroy()

- player_prepare(), player_unprepare()

- player_start(), player_stop(), player_pause()

위의 함수들로 Idle, Ready, Playing, Paused 상태를 관리합니다.


Player 상태 다이어그램


player_create()에서 재생을 위한 핸들을 생성해주면 Idle 상태로 진입합니다.

핸들을 이용하여 player_prepare()를 하면 비로소 재생할 준비를 합니다.

재생 준비가 되면 Ready 상태에 이르게 되는데요,

player_start()로 Playing 상태로 바뀌고,

player_pause()로는 Paused 상태로 바뀌며,

player_stop()을 실행하면 다시 ready 상태가 됩니다.


Player 상태 변이


위에서 언급한 상태 다이어그램을 함수 측면에서 살펴볼 수도 있습니다.

표에서는 각각의 함수를 실행하기 전에 수행해야할 pre-state를 확인할 수 있습니다.

대부분의 함수가 sync로 동작하기 때문에 절차적 프로그래밍을 하면 됩니다.

player_prepare_async()만이 async인데요, 드럼앱에서는 따로 사용하지 않았습니다.


우선, player 핸들을 생성하여 준비하는 단계를 살펴보겠습니다.

총 9개의 드럼이 있기 때문에 각각의 소리를 재생하기 위해서 9개의 player 핸들을 생성해야합니다.


static void init_base_player(app_data *ad)
{
player_create(&ad->player1);
player_set_uri(ad->player1, "/opt/usr/apps/org.tizen.drums/res/sounds/ride.wav");
player_prepare(ad->player1);

player_create(&ad->player2);
player_set_uri(ad->player2, "/opt/usr/apps/org.tizen.drums/res/sounds/crash.wav");
player_prepare(ad->player2);

player_create(&ad->player3);
player_set_uri(ad->player3, "/opt/usr/apps/org.tizen.drums/res/sounds/tom2.wav");
player_prepare(ad->player3);

player_create(&ad->player4);
player_set_uri(ad->player4, "/opt/usr/apps/org.tizen.drums/res/sounds/hihat2.wav");
player_prepare(ad->player4);

player_create(&ad->player5);
player_set_uri(ad->player5, "/opt/usr/apps/org.tizen.drums/res/sounds/hihat1.wav");
player_prepare(ad->player5);

player_create(&ad->player6);
player_set_uri(ad->player6, "/opt/usr/apps/org.tizen.drums/res/sounds/tom1.wav");
player_prepare(ad->player6);

player_create(&ad->player7);
player_set_uri(ad->player7, "/opt/usr/apps/org.tizen.drums/res/sounds/floor.wav");
player_prepare(ad->player7);

player_create(&ad->player8);
player_set_uri(ad->player8, "/opt/usr/apps/org.tizen.drums/res/sounds/snare.wav");
player_prepare(ad->player8);

player_create(&ad->player9);
player_set_uri(ad->player9, "/opt/usr/apps/org.tizen.drums/res/sounds/bass.wav");
player_prepare(ad->player9);
}


위의 함수를 보시면, player_create()를 9번 수행한 것을 확인할 수 있습니다.

그리고 획득한 핸들로 player_set_uri()를 사용하여 재생할 파일 경로를 입력하였습니다.

"file://"와 같은 prefix를 넣지 않고 바로 절대경로를 입력하여도 동작합니다.

파일 경로까지 입력하였으니 이제 재생을 위한 준비를 할 차례입니다.

player_prepare()함수를 사용하여 sync로 재생 준비를 마칩니다.


void play_audio(player_h player)
{
player_state_e player_state;
player_get_state(player, &player_state);
if (player_state == PLAYER_STATE_PLAYING) {
player_stop(player);
}
player_start(player);
}


이제 드럼을 터치하면 재생을 할 차례입니다.

재생을 하기에 앞서 현재 재생 중인지 여부를 확인합니다.

player_get_state() 함수를 사용하여 현재 상태를 확인할 수 있습니다.



함수를 통해 총 5가지 상태 중 하나의 값을 얻어옵니다.

만약 이미 플레이 중이라면,

player_get_stop()으로 플레이를 멈춥니다.

그리고 다시 player_start()로 재실행을 합니다.


드럼마다 이벤트 영역을 설정하여 play_audio() 함수를 실행하도록 합니다.

총 9개의 드럼이 제각각의 소리를 내는 것을 확인할 수 있습니다.

9개의 이벤트 영역을 설정하는 방법도 흥미로우니,

시간이 허락한다면 한 번 소스를 살펴보는 것도 좋습니다.


player를 위해 할당받은 자원을 정리할 차례입니다.

9개의 핸들에 대해 아래 두 함수를 이용하여 정리작업을 합니다.


    player_unprepare(app->player1);
    player_destroy(app->player1);


이상 아주 간단한 player 사용법이었습니다.

player에는 이외에도 굉장히 다양한 기능이 있습니다.

시간이 허락한다면 좀 더 복잡한 앱의 소스를 분석해보는 시간을 가져보겠습니다.


그럼 좋은 하루 보내세요~

끝_



* References

https://developer.tizen.org/

https://developer.tizen.org/community/tip-tech/drums-tizen

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__PLAYER__MODULE.html


안녕하세요, 타이젠 개발자 윤진입니다.


타이젠 앱개발과 관련하여 자주 접하는 질문들을 하나씩 포스팅하기로 마음 먹었었는데요,

(마음만 먹었습니다;)

근데 워낙 많은 질문이 들어와서...

내년이 되어도 모든 답변을 포스팅할 수 있을지 모르겠습니다.


일단 이번 포스팅에서는,

화면이 꺼지면 안되는 앱이 필수로 사용하는 전원 API를 살펴보도록 하겠습니다.


전원 관련 API는 총 4개가 있습니다.

여기서 CPU와 Display의 전원은 request & release 함수를 이용하여 제어하지요.

하지만, 2.4부터는 보다 강력하면서 사용하기도 쉬운 API가 추가되었습니다.

그에 따라 request & release API는 deprecated 수순을 밟고 있습니다.


그 대신 efl_util에서 window screen mode를 설정할 수 있도록 API를 제공합니다.

함수 이름에 직접적으로 언급되어 있듯,

이 함수는 윈도우의 상태를 기준으로 파워를 제어하게 됩니다.

윈도우가 화면에 보이는 상태에서만 위의 함수로 지정한 상태로 진입하고,

화면에서 완전히 사라지면 n초 후 화면은 꺼지게 됩니다.


EFL_UTIL_SCREEN_MODE_DEFAULT는 시간이 경과하면 화면을 끄고,

EFL_UTIL_SCREEN_MODE_ALWAYS_ON은 화면이 켜져있는 상태를 유지합니다.


기존에는 앱의 라이프사이클인 pause / resume 콜백에서 device power 함수를 사용하여,

- 앱이 pause가 되면 상시 전원 on에서 사용시만 on으로 변경하고,

- 앱이 resume이 되면 상시 전원 on 상태로 유지하였었는데요,


이제는 윈도우의 상태에 따라,

- 윈도우가 사라지면(곧, 앱이 pause가 되면), ALWAYS_ON 상태가 자동으로 해제되어 화면이 꺼지도록 제어가 됩니다.

- 반대로 윈도우가 나타나면(곧, 앱이 resume이 되면), ALWAYS_ON이 다시 설정되게 됩니다.

그렇기에 앱의 라이프 사이클 대신 기능의 라이프 사이클에 맞춰 함수를 사용하면 됩니다.

간단하지요? :)


그럼 오늘도 좋은 하루 보내세요~

끝_


* References

https://developer.tizen.org/community/tip-tech/keeping-screen-awake-until-pressing-hold-button

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__SYSTEM__DEVICE__POWER__MODULE.html

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__EFL__UTIL__MODULE.html

  1. 2015.12.11 23:00

    비밀댓글입니다


안녕하세요, 타이젠 개발자 윤진입니다.


타이젠 관련 행사를 진행하면 으레 받는 질문 중에 하나가 '인증'과 관련된 부분입니다.

타이젠 SDK로 소스를 빌드한 후,

패키지를 에뮬 혹은 타겟에 설치하고자 할 때 인증관련 에러를 접하게 되는데요,

알고나면 별거 아니지만 문제를 해결하기까지 시행착오를 겪는 경우가 아주 많지요.

따라서 그런 시행착오를 조금이나마 줄이고자,

타이젠 사이트에 정리되어있는 내용에 살 좀 붙여서 공유하고자 합니다.

한국어 보다 영어가 편리하신 분은 여기에서 참고하셔도 됩니다.

(위의 자료는 오픈소스그룹의 조재민 책임연구원께서 준비한 것으로 추정됩니다.)


SDK와 Z1 간에 개발자/디바이스 인증을 받는 법은 이미 포스팅한바 있습니다.

[Tizen] 타이젠 SDK와 Z1 연결이 되나요? 인증은 필수!

위의 포스팅은 전체적인 인증절차를 살피고자 문제없이 진행된다는 가정하에 쓰여졌었는데요,

처음 인증을 받고자 하는 분들은 위의 포스팅을 참고하시고,

문제가 생겼을 때 본 포스팅으로 도움을 얻으셨으면 좋겠네요.



* 인증을 위한 첫걸음, SDK Extension 설치하기

타이젠 플랫폼이 탑재된 상품은 견고한 보안을 갖추고자 다각도로 노력하고 있습니다.

따라서 Z1, Z3와 같은 모바일 상품이나,

Gear 시리즈와 같은 웨어러블 상품에서는 해킹위협을 원천차단하고자 합니다.

그 첫번째 단추가 검증되지 않은 앱을 설치하지 못하도록 막는 것입니다.

그렇기 때문에 복잡한 인증절차를 거칠 필요가 있습니다.

인증절차를 아직 밟지 않으셨다면 위에서 언급한 포스팅을 참고하여 인증을 받아주세요.

아래 링크를 참고하여 모바일 혹은 웨어러블 Extension을 설치하시면 됩니다.


- Mobile SDK Extension

http://developer.samsung.com/samsung-z


- Wearable SDK Extension

http://developer.samsung.com/technical-doc/view.do?v=T000000248



* Active secure profile is not set.
  Please check the signing configurations at Preferences > Security Profiles.

위의 에러메시지는 저자 & 장치 인증을 받지 않았을때 나타납니다.

Extension SDK를 설치하시고 저자 & 장치 인증을 먼저 받으세요.

그리고 Connection explorer에서 연결된 디바이스를 클릭합니다.

마우스 오른쪽 버튼을 눌러 메뉴를 띄운 후,

"Permit to install applications"를 선택해주세요.

(그러면 device-profile.xml을 /home/developer 디렉토리에 설치가 되죠.)

위의 절차를 정확히 수행했다면 더 이상 이런 에러가 발생하지 않을겁니다.



* 'Launching TizenApp' has encountered a problem.
  Error code: SIGNATURE_INVALID

위의 에러메시지를 자세히 읽어보면 "Check author certificates"라는 부분이 있습니다.

저자인증이 제대로 진행되지 않아서 발생하는 에러겠지요.

이미 인증을 모두 진행하셨더라도 저자 인증을 다시 진행해야합니다.

제대로 인증을 완료한 후 Connection explorer에서 연결된 디바이스를 클릭합니다.

마우스 오른쪽 버튼을 눌러 메뉴를 띄운 후,

"Permit to install applications"를 선택해주세요.

(그러면 device-profile.xml을 /home/developer 디렉토리에 설치가 되죠.)

위의 절차를 정확히 수행했다면 더 이상 이런 에러가 발생하지 않을겁니다.



* 'Launching basic' has encountered a problem.
   Errors occurred during the build.

팝업의 하단을 잘 살펴보면 "Invalid password"라는 문구가 보입니다.

인증서를 등록하셨다면 저자인증 파일을 등록하면서 패스워드를 입력하셨을 겁니다.

바로 그 패스워드가 잘못되었을 경우 위와 같은 에러가 발생합니다.

Preferences > Tizen SDK > Security Profiles

위의 경로로 진입하셔서 Author 인증시 입력한 패스워드를 다시 잘 입력해보세요.

만약 패스워드가 기억이 안나신다면 Author 인증를 새로 해주세요.



* 'Launching basic' has encountered a problem.
  Error occurred while signing the widget.
  Both an author and a first distributor must be required.
  Please check your profile information.

팝업 내용을 살펴보면 저자인증 부분이 잘못된 것을 알 수 있습니다.

저자인증시 입력한 패스워드를 다시 한 번 확인해주세요.

만약 패스워드가 기억이 안나신다면 Author 인증를 새로 해주세요.



* Registration failed.
  Reason: java.lang.Exception: Generic Exception caught.
  Given final block not properly padded.

생소한 자바에러가 보이지만 '등록(Registration)'과 관련된 부분이란 것을 눈치챌 수 있습니다.

만약 Legacy certificate로 저자 & 장치 인증을 하셨다면,

Legacy certificate 파일이 잘못되었을 수 있습니다.

제대로 된 Legacy certificate으로 다시 인증을 받아보시길 권해드립니다.


그게 아니라 저자 & 장치 인증을 각각 받았다면,

저자인증 입력한 패스워드가 잘못되었을 수도 있습니다.

저자인증을 위한 암호를 다시 한 번 입력해보세요.

암호가 기억나지 않는다면 다시 저자인증을 하시길 추천해드립니다.



* There is no certificate for the selected device.
  Please update your certificate.

위의 팝업을 만나면 장치인증 파일에 문제가 있을 수 있습니다.

SDK와 연결된 장치와 장치인증을 받은 장치가 맞는지 확인해보세요.

device-profile.xml 파일을 열어서 <TestDevice>의 DUID와 SDK 연결된 장치의 DUID를 비교하시면 됩니다.

만약 DUID가 다르다면 연결된 장치로 장치인증을 다시 받으셔야 합니다.



* Certificate has not been installed to device yet.
  Please perform 'permit to install applications' of the context menu in Connection Explorer.
  For more information, refer to Help Contents: Certificates.

위의 에러메시지는 저자 & 장치 인증이 제대로 수행되지 않았을때 나타날 수 있습니다.

인증을 하지 않으셨다면,

Extension SDK를 설치하시고 저자 & 장치 인증을 먼저 받으세요.


(인증을 이미 하신 경우 포함) 인증절차를 완료한 후,

Connection explorer에서 연결된 디바이스를 클릭합니다.

마우스 오른쪽 버튼을 눌러 메뉴를 띄운 후,

"Permit to install applications"까지 선택을 해주셔야 합니다.

(그러면 device-profile.xml을 /home/developer 디렉토리에 설치가 되죠.)

위의 절차를 정확히 수행했다면 더 이상 이런 에러가 발생하지 않을겁니다.



* 'Launching nativetest - Debug' has encountered a problem.

  Cannot create package.

패키지를 생성하지 못했다는 경고문구입니다.

문구가 구체적이지 않기 때문에 수정포인트를 잡을 수가 없네요.

이 문구는 certificate가 잘못되었을 확률이 높습니다.

Preferences > Tizen SDK > Security Profile

위의 경로에 진입하여 저자 & 장치 인증부터 다시 진행해보세요.



* 'Launching test - Debug' has encountered a problem.
  Cannot install application.

위의 에러는 패키지를 설치할 때 발생하는 에러입니다.

유감스럽게도 'Error message: Success'라고 되어 있기 때문에 더 난해졌습니다.

에러메시지가 '성공'이라고 하네요. 하핫;

이럴 때 좌절하고 싶으실지는 모르겠지만 조금만 참아주세요.


문구가 난해하기 때문에 딱부러진 해결책도 없습니다.

저자 & 장치인증서를 처음부터 다시 받아보세요.

그리고 Connection explorer에서 연결된 디바이스를 클릭합니다.

마우스 오른쪽 버튼을 눌러 메뉴를 띄운 후,

"Permit to install applications"를 선택해주세요.

(그러면 device-profile.xml을 /home/developer 디렉토리에 설치가 되죠.)

위의 절차를 정확히 수행했다면 더 이상 이런 에러가 발생하지 않을겁니다.


이상으로 인증실패 총정리편을 마치겠습니다.

그 외의 에러팝업도 있을 수 있겠죠?

여기에 언급되어 있지 않은 에러팝업을 보신다면,

tizen.org의 Q&A 게시판에서 도움을 받으시는게 가장 빠른 방법입니다.

그게 부담되신다면 답글을 남겨주세요.

담당자분께 확인하여 답변해드리겠습니다.

(시간이 좀 더 걸리겠지요.)


그럼 좋은 하루 보내세요~

끝_


* References

http://developer.samsung.com/samsung-z

http://developer.samsung.com/technical-doc/view.do?v=T000000248

https://developer.tizen.org/community/tip-tech/trouble-shooting-certification

  1. 하수 2016.07.19 01:06

    안녕하세요 타이젠 연습해보려는 학생입니다!! 간단히 native로 만들고 실행해보는데
    'Launching fakekakaotalk - Debug(1)' has encountered a problem
    The program file specified in the launch configuration des not exist

    이러는데 어떻게 해결해야하나요?? 어려운것도 없엇는데 벌써이러네요....

    • 안녕하세요. 제가 지금 러시아 오지탐험 중이라 직접 확인해볼 수가 없는데요. 심지어 인터넷도 너무 느려서 이 댓글을 확인하는것만 오분 정도 걸렸습니다. 하하. 죄송하지만 페이스북에 Tizen talks 그룹이 운영되고 있는데 거기서 한번 물어보시겠어요?


안녕하세요, 타이젠 개발자 윤진입니다.


3~4달쯤 전에 타이젠 스토어에 앱을 올렸습니다.

타이젠 스토어는 앱을 엄격하게 심사하는 것으로도 유명한데요,

(참고 : [Tizen Store] 타이젠 스토어에 앱올리기 전에 셀프체크하기)

셀프체크를 하고 앱을 업로드 하니 다행스럽게도 한 번에 통과할 수 있었습니다.


이번 포스팅에서는 타이젠 스토어에 등록된 앱에서,

타이젠 스토어 자체를 런치하는 방법을 공유하고자 합니다.

- 타이젠 스토어 메인 페이지

- 타이젠 스토어 앱 상세정보 페이지

- 타이젠 스토어 판매자 페이지

위의 세 가지 페이지로 진입할 수 있는 방법이 있습니다.


타이젠 스토어를 런치하기 위해서는 기본적으로 app_control API를 사용합니다.

app_control API는 이미 데브랩 등에서 여러 차례 발표를 했었는데요,

여기에서도 간단하게나마 파악하실 수 있습니다.

앱을 런칭하기 위해서는 privilege가 필요하니 manifest 파일에 아래 권한을 추가해주세요.

http://tizen.org/privilege/appmanager.launch


1. 타이젠 스토어 메인 페이지

타이젠 스토어 메인페이지를 띄우려면 app_control_set_app_id()를 사용하면 됩니다.

타이젠 스토어의 app id인 "org.tizen.tizenstore"를 인자로 넣어주세요.


#include <app_control.h>

app_control_h service = NULL;
int ret = -1;

ret = app_control_create(&service);
ret = app_control_set_app_id(service, "org.tizen.tizenstore");
ret = app_control_set_uri(service, "tizenstore://Main");
ret = app_control_set_operation(service, APP_CONTROL_OPERATION_VIEW);
ret = app_control_send_launch_request(service, appcontrol_callback, NULL);
app_control_destroy(service);


코드를 간결하게 표현하기 위해 에러처리는 생략합니다.

app_control_create()로 할당받은 메모리는 app_control_destroy()로 해제해주어야 합니다.

app_control_send_launch_request() 직후에 메모리를 해제하면 됩니다.


2. 타이젠 스토어 앱 상세정보 페이지

앱 상세정보 페이지에 진입하기 위해서는 우선 앱의 Content ID를 알아야 합니다.

공식 가이드에는 Package ID를 입력하라고 되어 있는데요,

실제 코드를 보면 Package ID 대신 Content ID를 넣어주고 있으니 착오없으시길 바랍니다.


Content ID는 앱을 등록할때 부여받는 ID입니다.

이미 등록한 앱이 있으시다면 Content ID를 http://seller.tizenstore.com에서 찾아보실 수 있습니다.



Seller Office > Applications > Content ID

위의 경로로 Content ID를 확인하실 수 있습니다.

이번에는 app_control_set_uri()에 "tizenstore://ProductDetail/<Content_ID>" 형식으로 채웁니다.

아래 루틴이 실행되면 타이젠 스토어 앱이 열리면서 지정된 앱 상세 페이지에 진입하게 됩니다.


#include <app_control.h>

app_control_h service = NULL;
int ret = -1;

ret = app_control_create(&service);
ret = app_control_set_app_id(service, "org.tizen.tizenstore");
ret = app_control_set_uri(service, "tizenstore://ProductDetail/<Content_ID>");
ret = app_control_set_operation(service, APP_CONTROL_OPERATION_VIEW);
ret = app_control_send_launch_request(service, NULL, NULL);
app_control_destroy(service);


3. 타이젠 스토어 판매자 페이지

타이젠 스토어에서 판매자 페이지로 진입하기 위해서는 우선 판매자 ID를 알아야 합니다.

판매자 ID도 "http://seller.tizenstore.com"에서 확인하실 수 있습니다.



Seller Office > Edit User(오른편 상단) > Basic Information

위의 경로로 진입하면 Basic Information 최하단에 Seller DeepLink를 확인하실 수 있습니다.

위의 ID를 "tizenstore://SellerApps/<Seller_ID>"의 형식으로 app_control_set_uri()에 채우세요.

그리고 런칭을 하면 판매자 페이지로 진입할 수 있습니다.


#include <app_control.h>

app_control_h service = NULL;
int ret = -1;

ret = app_control_create(&service);
ret = app_control_set_app_id(service, "org.tizen.tizenstore");
ret = app_control_set_uri(service, "tizenstore://SellerApps/<Seller_ID>");
ret = app_control_set_operation(service, APP_CONTROL_OPERATION_VIEW);
ret = app_control_send_launch_request(service, NULL, NULL);
app_control_destroy(service);


이상과 같이 Tizen Store에 연결하는 방법을 알아보았습니다.

궁극적으로 플랫폼 앱에서 다수의 앱을 연결할 때 사용하면 유용하겠네요.


그럼 좋은 하루 보내세요~

끝_


* References

https://developer.tizen.org/community/tip-tech/linking-your-application


안녕하세요, 타이젠 개발자 윤진입니다.


지난 포스팅에서는 audio in에 대해다뤘었는데요,

[Tizen] 타이젠 개발, Audio Input으로 녹음하기

이번에는 그에 대한 짝개념으로 Audio out을 다뤄보도록 하겠습니다.



audio out 계열의 함수도 audio in 계열의 함수와 유사한 점이 많습니다.

다만 in 계열이 읽어들이는 것에 초점을 맞추었다면,

out 계열은 출력하는 데에 초점이 맞춰져있습니다.

in에서 raw 데이터로 녹음을 하면 out에서 녹음된 raw 데이터를 재생합니다.

그 외에 전체적인 함수 사용법은 in이나 out이나 유사합니다.



audio out 계열 함수를 사용하려면 우선 디바이스 인스턴스를 생성해야 합니다.

audio_out_create() 함수로 디바이스 인스턴스를 생성할 수 있는데요,

sample rate, channel, type(depth)는 audio_in_create()에서도 동일하게 사용한 인수입니다.

하지만, 거기에 출력을 위해 sound_type이 추가로 들어갔습니다.



Sound manager의 session에서 사용하는 enum 값이 아닌,

Sound manager의 volume에서 사용하는 sound_type_e를 넣어주게 되어 있는데요,

audio_out 계열은 3rd party에서 사용하도록 공개된 Sound manager 의 session 보다,

System, Ringtone, Call, Voice와 같은 좀 더 넓은 선택지가 있어 보입니다.


하지만, 실제로 모든 세션을 사용할 수 있는 것은 아닙니다.

Sound manager에서 제공하는 sound_manager_set_session_type()에서 허용하는 세션으로만 설정하는 것이 맞아보입니다.



audio_out_ignore_session()은 audio_in_ignore_session()과 유사한 함수입니다.

본 함수는 audio_out으로 사운드 데이터를 출력할 때,

다른 세션의 output은 무시할 수 있도록 지정합니다.

- 곧, 현재 세션을 출력 중에 다른 세션을 시작해도 서로 무시하고,

- 다른 세션이 출력 중에 현재 세션을 출력해도 서로 무시하게 합니다.


하지만, 사운드 세션 관리는 본 함수를 사용하여 통제하는 것보다는,

Sound session manager에게 관리를 맡기는 것이 맞아 보입니다.


void play_file(char *file, int length, int ch)
{
    audio_out_h output;
    FILE* fp = fopen (file, "r");

    char * buf = malloc (length);

    printf ("start to play [%s][%d][%d]\n", file, length, ch);
    audio_out_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output);
    if (fread (buf, 1, length, fp) != length) {
        printf ("error!!!!\n");
    }

    audio_out_prepare(output);
    audio_out_write(output, buf, length);
    audio_out_unprepare(output);

    audio_out_destroy (output);

    fclose (fp);

    printf ("play done\n");
}


전체적인 동작은 위의 루틴을 보면서 설명해보겠습니다.

- audio_out_create()로 sound_type까지 확정하여 디바이스 인스턴스를 생성합니다.

- audio_out_prepare()로 디바이스 버퍼링에 데이터를 쓸 준비를 합니다.

- audio_out_write()를 이용하여 데이터를 디바이스에 출력합니다.

- audio_out_unprepare()로 디바이스 버퍼링에 디바이스 출력을 멈춥니다.

- audio_out_destroy()로 생성된 디바이스 인스턴스를 정리합니다.

synchronous하게 동작하기 때문에 audio_out_write()에서 장시간 블록됩니다.


스레드 블록을 막고 싶으면 asynchronous하게 동작하는 함수를 사용하면 됩니다.

이 부분도 예제 코드를 보면서 설명하겠습니다.


int audio_io_async_test(int mode)
{
    char *buffer = NULL;
    FILE* fp_r = NULL;

    int ret, size;
    int i = 0;

    ret = audio_out_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, SOUND_TYPE_MEDIA, &output);
    if (ret != AUDIO_IO_ERROR_NONE) {
        printf("audio_out_create failed.\n");
        return 0;
    }

    ret = audio_out_set_stream_cb(output, _audio_io_stream_write_cb, NULL);
    if (ret != AUDIO_IO_ERROR_NONE) {
        printf("audio_out_set_stream_cb failed.\n");
        audio_out_destroy(output);
        return 0;
    }

    fp_r = fopen( "/tmp/pcm.raw", "r");
    if (!fp_r) {
        audio_out_destroy(output);
        return 0;
    }

    ret = audio_out_prepare(output);
    if (ret != 0) {
        printf("audio_out_prepare failed.\n");
        audio_out_destroy(output);
        return 0;
    }

    for (i = 0; i < 10; i++) {
        printf ("-------- %d -------\n",i);
        usleep (1000000);
    }

    audio_out_unprepare(output);
    audio_out_destroy(output);

    fclose(fp_r);

    return 0;
}


위의 루틴으로 audio_out을 asynchronous하게 진행할 수 있습니다.

- 우선, 데이터 출력을 위해 audio_out_create()로 디바이스 인스턴스를 생성합니다.

- 그리고 audio_out_set_stream_cb()으로 콜백을 등록합니다. 콜백은 장치상황에 맞춰 불려집니다.

- audio_out_prepare()로 디바이스가 출력을 시작하게 됩니다.

- audio_out_unprepare()로 디바이스가 출력을 멈춥니다.

- audio_out_destroy()로 디바이스 인스턴스를 해제합니다.


static void _audio_io_stream_write_cb(audio_out_h handle, size_t nbytes, void *userdata)
{
    char *buffer = NULL;
    int ret = 0;

    if (nbytes <= 0) {
        printf ("Error!!!! %d", nbytes);
        return;
    }

    buffer = malloc(nbytes);
    memset(buffer, 0, nbytes);
   
    ret = fread(buffer, 1, nbytes, fp_r);
    if (ret != nbytes) {
        printf("Error!!!! %d/%d", ret, nbytes);
    }  
   
    ret = audio_out_write(handle, buffer, nbytes);
    if (ret > AUDIO_IO_ERROR_NONE) {
        printf("audio write success. buffer(%p), nbytes(%d)\n", buffer, nbytes);
    }
        audio_out_drain(handle);     free(buffer);
}


위의 루틴은 audio_out_set_stream_cb()으로 등록한 콜백함수입니다.

- 콜백함수가 불리면 fread()를 이용하여 파일에서 데이터를 읽어온 후,

- audio_out_write()로 디바이스에 해당 데이터를 출력하게 됩니다.

  이 함수는 write가 끝날 때까지 블록하게 됩니다.

- audio_out_drain()은 pcm 데이터가 디바이스로 완전히 나갈때까지 블록시킵니다.


이상으로 간단하게 audio out 계열 함수를 살펴보았습니다.

audio out 코드를 보며 추가로 파봐야할 포인트를 몇 개 찾았는데요,

공유할 만한 사실이 발견되면,

이 포스팅에 지속적으로 업데이트하도록 하겠습니다.


그럼 좋은 하루 보내세요~

끝_


* References

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__AUDIO__OUT__MODULE.html

git://review.tizen.org/framework/api/audio-io


안녕하세요, 타이젠 개발자 윤진입니다.


이번 그리고 다음 포스팅에 걸쳐 Audio I/O에 관해 다룰 예정입니다.

Audio I/O는 사운드를 raw 데이터(PCM)로 녹음하거나 재생할 때 사용합니다.

raw 데이터(PCM)란 압축하거나 다른 형태로 인코딩하지 않은 데이터를 의미하지요.



Audio input과 관련된 18개의 API가 있는데요,

위의 API를 사용하기 위해서는 microphone feature를 추가해주어야 합니다.

http://tizen.org/feature/microphone

앱의 manifest 파일에 위의 feature를 추가해주세요.

(참고 : https://developer.tizen.org/development/tools/native-tools/manifest-text-editor#feature)



Audio를 녹음하기 위해서는 우선 device instance를 만들어야 합니다.

device instance는 audio_in_create()으로 만들 수 있지요.

위의 함수를 사용하기 위해서는 privilege가 필요하니 manifest에서 권한도 추가해주셔야 돼요.

http://tizen.org/privilege/recorder


인자는 총 네 개로 세 개는 in-parameter이고 마지막 하나는 out-parameter입니다.

(타이젠은 기본적으로 out-parameter를 활용하여 인스턴스를 넘겨주는 패턴을 사용합니다.) 

sample rate, channel, type(depth)을 in-parameter로 넘겨주면,

out-parameter로 input 값이 넘어오는데 이 input 값으로 audio_in 함수 전체를 통제하게 됩니다.

input 값으로 audio_in 계열의 함수를 사용한 후,

audio_in_destroy()로 메모리를 정리해주면 됩니다.


참고로 audio_in_create_loopback()은 출력장치로 나가는 소리를 캡쳐하는 기능입니다.

- 스피커로 나가는 출력데이터를 audio_in_create_loopback()로 가져와서,

- audio_out_create()로 나가는 루틴에 대입하여 echo를 제거할 때 사용할 수 있습니다.

하지만, 이 함수를 사용하는 것은 좀 더 따져봐야할 것으로 보입니다.

Tizen의 다음 버전에서 이 기능을 지원할지는 확실치가 않아서요.

(참고로 이 부분은 멀티미디어 전문가인 '신' 책임연구원님(실명언급해도 될까요?)의 도움을 받았습니다)



audio_in_create() 직후에 audio_in_ignore_session()을 사용할 수 있습니다.

함수 설명을 보면,

"Ignores session for input"이라고 되어 있는데요(너무 단촐하네요).

다른 세션의 동작과 상관없이 녹음을 진행하기 위해 공개된 API입니다.

- 곧, 녹음을 시작할 때 타 세션을 interrupt 하지 않고,

- 타 세션이 시작하더라도 interrupt 받지 않습니다.

하지만, 기본적으로 세션관리는 Sound session manager에서 하고 있습니다.

따라서 ignore session을 이용하여 인위적으로 조절하지 않는게 좋겠네요.


int audio_io_test(int length, int num, int ch)
{
    int ret, size, i;
    audio_in_h input;
    if ((ret = audio_in_create(44100, ch_table[ch] ,AUDIO_SAMPLE_TYPE_S16_LE, &input)) == AUDIO_IO_ERROR_NONE) {
        ret = audio_in_ignore_session(input);
        if (ret != 0) {
            printf ("ERROR, set session mix\n");
            audio_in_destroy(input);
            return 0;
        }

        ret = audio_in_prepare(input);
        if (ret != 0) {
            printf ("ERROR, prepare\n");
            audio_in_destroy(input);
            return 0;
        }

        FILE* fp = fopen (DUMP_FILE, "wb+");

        if ((ret = audio_in_get_buffer_size(input, &size)) == AUDIO_IO_ERROR_NONE) {
            size = length;
            char *buffer = alloca(size);

            for (i=0; i<num; i++) {
                printf ("### loop = %d ============== \n", i);
                if ((ret = audio_in_read(input, (void*)buffer, size)) > AUDIO_IO_ERROR_NONE) {
                    fwrite (buffer, size, sizeof(char), fp);
                    printf ("PASS, size=%d, ret=%d\n", size, ret);
                }
                else {
                    printf ("FAIL, size=%d, ret=%d\n", size, ret);
                }
            }
        }

        fclose (fp);

        audio_in_destroy(input);
    }

    play_file (DUMP_FILE, length*num, ch);

    return 1;
}


위의 함수를 통해 audio_in 루틴을 전체적으로 파악할 수 있습니다.

- audio_in_create()로 디바이스 인스턴스를 하나 만들고,

- audio_in_ignore_session()으로 타 세션이 방해하지 못하도록 설정하고,

- audio_in_prepare()로 장치에서 버퍼링을 시작합니다.

- audio_in_get_buffer_size()로 시스템에서 넘겨주는 (권장) 버퍼 사이즈를 확인합니다.

  여기 있는 버퍼사이즈를 확인하여 audio_in_read()에서 버퍼를 사용합니다.

- audio_in_read()로 버퍼에 있는 데이터를 읽어 옵니다.

  synchronous하게 동작하는 API이기 때문에 데이터를 읽는 동안 블록됩니다.

- audio_in_destroy()로 최종적으로 디바이스 인스턴스를 정리합니다.


synchronous하게 동작하는 루틴이 보았다면,

이번에는 asynchronous하게 동작하는 루틴을 볼 차례입니다.


int audio_io_async_test(void)
{
    char *buffer = NULL;
    audio_in_h input;
    FILE* fp_w = NULL;
    int ret, size;
    int i = 0;
   
    ret = audio_in_create(44100, AUDIO_CHANNEL_STEREO , AUDIO_SAMPLE_TYPE_S16_LE, &input);
    if(ret != AUDIO_IO_ERROR_NONE) {
        printf ("audio_in_create_ex failed. \n");
        return 0;
    }
   
    ret = audio_in_set_stream_cb(input, _audio_io_stream_read_cb, NULL);
    if(ret != AUDIO_IO_ERROR_NONE) {
        printf ("audio_in_set_stream_cb failed. \n");
        return 0;
    }
   
    fp_w = fopen("/tmp/pcm_w.raw", "w");
    if (!fp_w) {
        printf ("cannot open a file\n");
        audio_in_destroy(input);
        return 0;
    }
   
    ret = audio_in_prepare(input);
    if (ret != 0) {
        printf ("audio_in_prepare failed.\n");
        audio_in_destroy(input);
        return 0;
    } else {
        ret = audio_in_get_buffer_size(input, &size);
        if(ret != AUDIO_IO_ERROR_NONE) {
            printf ("audio_in_get_buffer_size failed.\n");
            return 0;
        }
        else {
            printf("size(%d)\n", size);
            buffer = alloca(size);
        }
    }
   
    if(buffer == NULL) {
        printf("buffer is null\n");
        return 0;
    }
   
    printf ("loop start\n");
    for (i = 0; i < 10; i++) {
        printf ("-------- %d -------\n",i);
        usleep (1000000);
    }
   
    printf ("audio_in_unprepare\n");
    audio_in_unprepare(input);
    printf ("audio_in_destroy\n");
    audio_in_destroy(input);
   
    fclose(fp_w);
   
    return 0;
}


stream과 관련된 루틴에서는 asynchronous하게 동작하도록 콜백함수를 만들어 줘야하는데요,

콜백함수를 등록하는 루틴을 보고 콜백함수 자체를 살펴보겠습니다.

- audio_in_create()로 다비이스 인스턴스를 하나 만들어둡니다.

- audio_in_set_stream_cb()으로 asynchronous하게 이벤트를 받아 처리할 함수를 등록합니다.

- audio_in_prepare()로 디바이스에서 버퍼링을 시작하고,

- audio_in_unprepare()로 녹음을 중지합니다.

- audio_in_destroy()로 디바이스 인스턴스로 할당받은 메모리를 정리합니다.


자, 이번에는 콜백함수의 루틴을 살펴보도록 하겠습니다.


static void _audio_io_stream_read_cb (audio_in_h handle, size_t nbytes, void *userdata)
{
    const void * buffer = NULL;
       
    if (nbytes > 0) {
        audio_in_peek(handle, &buffer, &nbytes);
        if (fp_w) {
            fwrite(buffer, sizeof(char), nbytes, fp_w);
        }
        audio_in_drop (handle);
    }
}


콜백함수에서는 audio_in_peek()와 audio_in_drop() 함수를 사용할 수 있습니다.

위의 함수는 오직 콜백함수 내에서만 동작하지요.

audio_in_peek()로 버퍼링된 데이터를 buffer 인자로 받아와서 사용할 수 있습니다.

여기서는 버퍼를 fwrite를 사용하여 파일에 기록하였습니다.

그리고 나서 audio_in_drop()으로 버퍼를 정리해주었지요.


이상과 같이 audio_in 계열의 함수를 살펴보았습니다.

audio_in과 같이 raw 데이터를 다루는 함수는 기본지식이 없으면 다루기 힘듭니다.

이 기회에 학부때 중간고사용으로 공부하고 바로 까먹은 것들을 들춰봐야겠습니다.

다음 포스팅에서는 audio_out 계열의 함수를 훑어볼께요~


그럼 좋은 하루 보내세요~

끝_


* References

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__AUDIO__IN__MODULE.html

https://en.wikipedia.org/wiki/Pulse-code_modulation

https://en.wikipedia.org/wiki/Echo_suppression_and_cancellation

https://developer.tizen.org/development/tools/native-tools/manifest-text-editor#feature

git://review.tizen.org/framework/api/audio-io


안녕하세요, 타이젠 개발자 윤진입니다.


본 포스팅에 앞서 sound manager를 두 차례 다뤘는데요,

[Tizen] 타이젠 개발, Sound manager로 볼륨을 조절하기

[Tizen] 타이젠 개발, Sound manager로 세션을 조절하기

이번 포스팅에서는 Tone player로 사전정의된 음색을 재생/정지하는 방법을 다루겠습니다.



tone_player의 API는 단 2개입니다.

tone_player_start()로 재생을 하고 tone_player_stop()으로 정지를 합니다.

tone_player_start()에 duration_ms을 넣어주기 때문에,

굳이 tone_player_stop()을 사용하지 않아도 됩니다.

tone_player_start()의 첫번째 인자로 tone type을 넘겨줍니다.

tone type에는 총 111개의 내장 타입이 존재합니다.


/**
 * @brief Enumeration of tone.
 * @since_tizen 2.3
 */
typedef enum
{
    TONE_TYPE_DEFAULT = 0,            /**< The default tone */
    TONE_TYPE_DTMF_0 = 0,                /**< Predefined DTMF 0 */
    TONE_TYPE_DTMF_1,                 /**< Predefined DTMF 1 */
    TONE_TYPE_DTMF_2,                /**< Predefined DTMF 2 */
    TONE_TYPE_DTMF_3,                /**< Predefined DTMF 3 */
    TONE_TYPE_DTMF_4,                /**< Predefined DTMF 4 */
    TONE_TYPE_DTMF_5,                /**< Predefined DTMF 5 */
    TONE_TYPE_DTMF_6,                /**< Predefined DTMF 6 */
    TONE_TYPE_DTMF_7,                /**< Predefined DTMF 7 */
    TONE_TYPE_DTMF_8,                /**< Predefined DTMF 8 */
    TONE_TYPE_DTMF_9,                /**< Predefined DTMF 9 */
    TONE_TYPE_DTMF_S,               /**< Predefined DTMF Star - Asterisk (*) */
    TONE_TYPE_DTMF_P,                /**< Predefined DTMF sharP (#) */
    TONE_TYPE_DTMF_A,                /**< Predefined DTMF A (A) */
    TONE_TYPE_DTMF_B,                /**< Predefined DTMF B (B) */
    TONE_TYPE_DTMF_C,                /**< Predefined DTMF C (C) */
    TONE_TYPE_DTMF_D,                /**< Predefined DTMF D (D) */
    TONE_TYPE_SUP_DIAL,     /**< Call supervisory tone, Dial tone: CEPT: 425Hz, continuous */
    TONE_TYPE_ANSI_DIAL,    /**< Call supervisory tone, Dial tone: ANSI (IS-95): 350Hz+440Hz, continuous */
    TONE_TYPE_JAPAN_DIAL,    /**< Call supervisory tone, Dial tone: JAPAN: 400Hz, continuous */
    TONE_TYPE_SUP_BUSY,    /**< Call supervisory tone, Busy: CEPT: 425Hz, 500ms ON, 500ms OFF... */
    TONE_TYPE_ANSI_BUSY,     /**< Call supervisory tone, Busy: ANSI (IS-95): 480Hz+620Hz, 500ms ON, 500ms OFF... */
    TONE_TYPE_JAPAN_BUSY,     /**< Call supervisory tone, Busy: JAPAN: 400Hz, 500ms ON, 500ms OFF... */
    TONE_TYPE_SUP_CONGESTION,   /**< Call supervisory tone, Congestion: CEPT, JAPAN: 425Hz, 200ms ON, 200ms OFF */
    TONE_TYPE_ANSI_CONGESTION,  /**< Call supervisory tone, Congestion: ANSI (IS-95): 480Hz+620Hz, 250ms ON, 250ms OFF... */
    TONE_TYPE_SUP_RADIO_ACK,   /**< Call supervisory tone, Radio path acknowledgment : CEPT, ANSI: 425Hz, 200ms ON  */
    TONE_TYPE_JAPAN_RADIO_ACK,  /**< Call supervisory tone, Radio path acknowledgment : JAPAN: 400Hz, 1s ON, 2s OFF...*/
    TONE_TYPE_SUP_RADIO_NOTAVAIL,  /**< Call supervisory tone, Radio path not available: 425Hz, 200ms ON, 200 OFF 3 bursts */
    TONE_TYPE_SUP_ERROR,    /**< Call supervisory tone, Error/Special info: 950Hz+1400Hz+1800Hz, 330ms ON, 1s OFF... */
    TONE_TYPE_SUP_CALL_WAITING,  /**< Call supervisory tone, Call Waiting: CEPT, JAPAN: 425Hz, 200ms ON, 600ms OFF, 200ms ON, 3s OFF... */
    TONE_TYPE_ANSI_CALL_WAITING,  /**< Call supervisory tone, Call Waiting: ANSI (IS-95): 440 Hz, 300 ms ON, 9.7 s OFF, (100 ms ON, 100 ms OFF, 100 ms ON, 9.7s OFF ...) */
    TONE_TYPE_SUP_RINGTONE,   /**< Call supervisory tone, Ring Tone: CEPT, JAPAN: 425Hz, 1s ON, 4s OFF... */
    TONE_TYPE_ANSI_RINGTONE,   /**< Call supervisory tone, Ring Tone: ANSI (IS-95): 440Hz + 480Hz, 2s ON, 4s OFF... */
    TONE_TYPE_PROP_BEEP,    /**< General beep: 400Hz+1200Hz, 35ms ON */
    TONE_TYPE_PROP_ACK,     /**< Proprietary tone, positive acknowledgment: 1200Hz, 100ms ON, 100ms OFF 2 bursts */
    TONE_TYPE_PROP_NACK,     /**< Proprietary tone, negative acknowledgment: 300Hz+400Hz+500Hz, 400ms ON */
    TONE_TYPE_PROP_PROMPT,    /**< Proprietary tone, prompt tone: 400Hz+1200Hz, 200ms ON  */
    TONE_TYPE_PROP_BEEP2,     /**< Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON */
    TONE_TYPE_SUP_INTERCEPT,       /**< Call supervisory tone (IS-95), intercept tone: alternating 440 Hz and 620 Hz tones, each on for 250 ms */
    TONE_TYPE_SUP_INTERCEPT_ABBREV,    /**< Call supervisory tone (IS-95), abbreviated intercept: intercept tone limited to 4 seconds */
    TONE_TYPE_SUP_CONGESTION_ABBREV,     /**< Call supervisory tone (IS-95), abbreviated congestion: congestion tone limited to 4 seconds */
    TONE_TYPE_SUP_CONFIRM,       /**< Call supervisory tone (IS-95), confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle */
    TONE_TYPE_SUP_PIP,        /**< Call supervisory tone (IS-95), pip tone: four bursts of a 480 Hz tone (0.1 s on, 0.1 s off) */
    TONE_TYPE_CDMA_DIAL_TONE_LITE,     /**< 425Hz continuous */
    TONE_TYPE_CDMA_NETWORK_USA_RINGBACK,   /**< CDMA USA Ringback: 440Hz+480Hz 2s ON, 4000 OFF ... */
    TONE_TYPE_CDMA_INTERCEPT,      /**< CDMA Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON ... */
    TONE_TYPE_CDMA_ABBR_INTERCEPT,     /**< CDMA Abbr Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON */
    TONE_TYPE_CDMA_REORDER,       /**< CDMA Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF... */
    TONE_TYPE_CDMA_ABBR_REORDER,     /**< CDMA Abbr Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF repeated for 8 times */
    TONE_TYPE_CDMA_NETWORK_BUSY,     /**< CDMA Network Busy tone: 480Hz+620Hz 500ms ON, 500ms OFF continuous */
    TONE_TYPE_CDMA_CONFIRM,       /**< CDMA Confirm tone: 350Hz+440Hz 100ms ON, 100ms OFF repeated for 3 times */
    TONE_TYPE_CDMA_ANSWER,       /**< CDMA answer tone: silent tone - definition Frequency 0, 0ms ON, 0ms OFF */
    TONE_TYPE_CDMA_NETWORK_CALLWAITING,    /**< CDMA Network Callwaiting tone: 440Hz 300ms ON */
    TONE_TYPE_CDMA_PIP,        /**< CDMA PIP tone: 480Hz 100ms ON, 100ms OFF repeated for 4 times */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_NORMAL,   /**< ISDN Call Signal Normal tone: {2091Hz 32ms ON, 2556 64ms ON} 20 times, 2091 32ms ON, 2556 48ms ON, 4s OFF */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP,  /**< ISDN Call Signal Intergroup tone: {2091Hz 32ms ON, 2556 64ms ON} 8 times, 2091Hz 32ms ON, 400ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 8times, 2091Hz 32ms ON, 4s OFF */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_SP_PRI,   /**< ISDN Call Signal SP PRI tone:{2091Hz 32ms ON, 2556 64ms ON} 4 times 2091Hz 16ms ON, 200ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 4 times, 2091Hz 16ms ON, 200ms OFF */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_PAT3,   /**< SDN Call sign PAT3 tone: silent tone */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_PING_RING,  /**< ISDN Ping Ring tone: {2091Hz 32ms ON, 2556Hz 64ms ON} 5 times 2091Hz 20ms ON */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_PAT5,   /**< ISDN Pat5 tone: silent tone */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_PAT6,   /**< ISDN Pat6 tone: silent tone */
    TONE_TYPE_CDMA_CALL_SIGNAL_ISDN_PAT7,   /**< ISDN Pat7 tone: silent tone */
    TONE_TYPE_CDMA_HIGH_L,       /**< TONE_CDMA_HIGH_L tone: {3700Hz 25ms, 4000Hz 25ms} 40 times 4000ms OFF, Repeat .... */
    TONE_TYPE_CDMA_MED_L,       /**< TONE_CDMA_MED_L tone: {2600Hz 25ms, 2900Hz 25ms} 40 times 4000ms OFF, Repeat .... */
    TONE_TYPE_CDMA_LOW_L,       /**< TONE_CDMA_LOW_L tone: {1300Hz 25ms, 1450Hz 25ms} 40 times, 4000ms OFF, Repeat .... */
    TONE_TYPE_CDMA_HIGH_SS,       /**< CDMA HIGH SS tone: {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 400ms OFF, repeat .... */
    TONE_TYPE_CDMA_MED_SS,       /**< CDMA MED SS tone: {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 400ms OFF, repeat .... */
    TONE_TYPE_CDMA_LOW_SS,       /**< CDMA LOW SS tone: {1300z 25ms, 1450Hz 25ms} repeat 16 times, 400ms OFF, repeat .... */
    TONE_TYPE_CDMA_HIGH_SSL,       /**< CDMA HIGH SSL tone: {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 16 times, 4000ms OFF, repeat ... */
    TONE_TYPE_CDMA_MED_SSL,       /**< CDMA MED SSL tone: {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 16 times, 4000ms OFF, repeat ... */
    TONE_TYPE_CDMA_LOW_SSL,       /**< CDMA LOW SSL tone: {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 16 times, 4000ms OFF, repeat ... */
    TONE_TYPE_CDMA_HIGH_SS_2,      /**< CDMA HIGH SS2 tone: {3700Hz 25ms, 4000Hz 25ms} 20 times, 1000ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 3000ms OFF, repeat .... */
    TONE_TYPE_CDMA_MED_SS_2,       /**< CDMA MED SS2 tone: {2600Hz 25ms, 2900Hz 25ms} 20 times, 1000ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 3000ms OFF, repeat .... */
    TONE_TYPE_CDMA_LOW_SS_2,       /**< CDMA LOW SS2 tone: {1300Hz 25ms, 1450Hz 25ms} 20 times, 1000ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 3000ms OFF, repeat .... */
    TONE_TYPE_CDMA_HIGH_SLS,       /**< CDMA HIGH SLS tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 3000ms OFF, REPEAT */
    TONE_TYPE_CDMA_MED_SLS,       /**< CDMA MED SLS tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 3000ms OFF, REPEAT */
    TONE_TYPE_CDMA_LOW_SLS,       /**< CDMA LOW SLS tone: {1300Hz 25ms, 1450Hz 25ms} 10 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 10 times, 3000ms OFF, REPEAT */
    TONE_TYPE_CDMA_HIGH_S_X4,      /**< CDMA HIGH S X4 tone: {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 2500ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_MED_S_X4,       /**< CDMA MED S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_LOW_S_X4,       /**< CDMA LOW S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_HIGH_PBX_L,      /**< CDMA HIGH PBX L: {3700Hz 25ms, 4000Hz 25ms}20 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_MED_PBX_L,      /**< CDMA MED PBX L: {2600Hz 25ms, 2900Hz 25ms}20 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_LOW_PBX_L,      /**< CDMA LOW PBX L: {1300Hz 25ms,1450Hz 25ms}20 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_HIGH_PBX_SS,      /**< CDMA HIGH PBX SS tone: {3700Hz 25ms, 4000Hz 25ms} 8 times 200 ms OFF, {3700Hz 25ms 4000Hz 25ms}8 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_MED_PBX_SS,      /**< CDMA MED PBX SS tone: {2600Hz 25ms, 2900Hz 25ms} 8 times 200 ms OFF, {2600Hz 25ms 2900Hz 25ms}8 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_LOW_PBX_SS,      /**< CDMA LOW PBX SS tone: {1300Hz 25ms, 1450Hz 25ms} 8 times 200 ms OFF, {1300Hz 25ms 1450Hz 25ms}8 times, 2000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_HIGH_PBX_SSL,      /**< CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 1000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_MED_PBX_SSL,      /**< CDMA MED PBX SSL tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 1000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_LOW_PBX_SSL,      /**< CDMA LOW PBX SSL tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 1000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_HIGH_PBX_SLS,      /**< CDMA HIGH PBX SLS tone:{3700Hz 25ms, 4000Hz 25ms} 8 times 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 1000ms OFF, REPEAT....  */
    TONE_TYPE_CDMA_MED_PBX_SLS,      /**< CDMA MED PBX SLS tone:{2600Hz 25ms, 2900Hz 25ms} 8 times 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 1000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_LOW_PBX_SLS,      /**< CDMA LOW PBX SLS tone:{1300Hz 25ms, 1450Hz 25ms} 8 times 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 1000ms OFF, REPEAT.... */
    TONE_TYPE_CDMA_HIGH_PBX_S_X4,     /**< CDMA HIGH PBX X S4 tone: {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 800ms OFF, REPEAT... */
    TONE_TYPE_CDMA_MED_PBX_S_X4,      /**< CDMA MED PBX X S4 tone: {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 800ms OFF, REPEAT... */
    TONE_TYPE_CDMA_LOW_PBX_S_X4,      /**< CDMA LOW PBX X S4 tone: {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 800ms OFF, REPEAT... */
    TONE_TYPE_CDMA_ALERT_NETWORK_LITE,    /**< CDMA Alert Network Lite tone: 1109Hz 62ms ON, 784Hz 62ms ON, 740Hz 62ms ON 622Hz 62ms ON, 1109Hz 62ms ON */
    TONE_TYPE_CDMA_ALERT_AUTOREDIAL_LITE,   /**< CDMA Alert Auto Redial tone: {1245Hz 62ms ON, 659Hz 62ms ON} 3 times, 1245 62ms ON */
    TONE_TYPE_CDMA_ONE_MIN_BEEP,      /**< CDMA One Min Beep tone: 1150Hz+770Hz 400ms ON */
    TONE_TYPE_CDMA_KEYPAD_VOLUME_KEY_LITE,   /**< CDMA KEYPAD Volume key lite tone: 941Hz+1477Hz 120ms ON */
    TONE_TYPE_CDMA_PRESSHOLDKEY_LITE,    /**< CDMA PRESSHOLDKEY LITE tone: 587Hz 375ms ON, 1175Hz 125ms ON */
    TONE_TYPE_CDMA_ALERT_INCALL_LITE,     /**< CDMA ALERT INCALL LITE tone: 587Hz 62ms, 784 62ms, 831Hz 62ms, 784Hz 62ms, 1109 62ms, 784Hz 62ms, 831Hz 62ms, 784Hz 62ms */
    TONE_TYPE_CDMA_EMERGENCY_RINGBACK,    /**< CDMA EMERGENCY RINGBACK tone: {941Hz 125ms ON, 10ms OFF} 3times 4990ms OFF, REPEAT... */
    TONE_TYPE_CDMA_ALERT_CALL_GUARD,    /**< CDMA ALERT CALL GUARD tone: {1319Hz 125ms ON, 125ms OFF} 3 times */
    TONE_TYPE_CDMA_SOFT_ERROR_LITE,     /**< CDMA SOFT ERROR LITE tone: 1047Hz 125ms ON, 370Hz 125ms */
    TONE_TYPE_CDMA_CALLDROP_LITE,     /**< CDMA CALLDROP LITE tone: 1480Hz 125ms, 1397Hz 125ms, 784Hz 125ms */
    TONE_TYPE_CDMA_NETWORK_BUSY_ONE_SHOT,   /**< CDMA_NETWORK_BUSY_ONE_SHOT tone: 425Hz 500ms ON, 500ms OFF */
    TONE_TYPE_CDMA_ABBR_ALERT,      /**< CDMA_ABBR_ALERT tone: 1150Hz+770Hz 400ms ON */
    TONE_TYPE_CDMA_SIGNAL_OFF,    /**< CDMA_SIGNAL_OFF - silent tone */
    TONE_TYPE_USER_DEFINED_LOW_FRE,                    /**< User Defined Tone: 100Hz continuous */
    TONE_TYPE_USER_DEFINED_MED_FRE,                    /**< User Defined Tone: 200Hz continuous */
    TONE_TYPE_USER_DEFINED_HIGH_FRE                   /**< User Defined Tone: 300Hz continuous */
} tone_type_e;


Call과 관련된 온갖 종류의 톤이 명시되어 있습니다.


static Eina_Bool _clk_beep_play_cb(void *data)
{
    tone_player_start(TONE_TYPE_PROP_ACK, SOUND_TYPE_ALARM, 400, NULL);
    return ECORE_CALLBACK_RENEW;
}


위의 코드는 clock 앱에서 sound를 제어하는 부분에서 가져왔습니다.

duration_ms를 400으로 주고 있기에 400ms가 지나면 저절로 멈춥니다.

따라서 따로 tone_player_stop()을 사용할 필요가 없습니다.


tone_player_stop()은,

버튼을 누르면 재생하고 손을 떼면 정지하는 상황에서 사용하면 됩니다.


tone play는 111가지 타입 중 사용목적에 맞는 톤을 고르는 것이 중요합니다.

enum 값으로 의미를 확인하고 실제로 소리를 들어본 후 루틴에 반영하세요.


tone player를 위한 샘플앱이 있습니다.

New > Tizen Native Project > Online Sample > Multimedia > Media

Tizen 2.4 IDE에서 위의 경로로 샘플앱을 생성하세요.


static const tone_type_e _tone_list[] = { 
    TONE_TYPE_DTMF_0,
    TONE_TYPE_DTMF_1,
    TONE_TYPE_DTMF_2,
    TONE_TYPE_DTMF_3,
    TONE_TYPE_DTMF_4,
    TONE_TYPE_DTMF_5,
    TONE_TYPE_DTMF_6,
    TONE_TYPE_DTMF_7,
    TONE_TYPE_DTMF_8,
    TONE_TYPE_DTMF_9,
    TONE_TYPE_DTMF_S,
    TONE_TYPE_DTMF_P,
    TONE_TYPE_DTMF_A,
    TONE_TYPE_DTMF_B,
    TONE_TYPE_DTMF_C,
    TONE_TYPE_DTMF_D
};


위의 tone type을 버튼을 눌러 하나씩 확인할 수 있습니다.

Media/src/audio/src/tone_player_view.c를 참고하시면 됩니다.


그럼 오늘은 이만 마치겠습니다.

좋은 하루 보내세요~


끝_


* References

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__TONE__PLAYER__MODULE.html

  1. 2015.12.01 00:29

    비밀댓글입니다


안녕하세요, 타이젠 개발자 윤진입니다.


지난 포스팅에서는 sound manager의 volume 부분을 살펴보았는데요,

[Tizen] 타이젠 개발, Sound manager로 볼륨을 조절하기

이번 포스팅에서는 sound manager의 session 부분을 보도록 하겠습니다.


세션 API


session과 관련하여 공개된 함수는 위의 10개가 전부입니다.

각각의 함수를 살펴보기에 앞서,

session type을 하나씩 먼저 언급해보도록 하겠습니다.



플랫폼 개발자 입장에서 살펴보면,

Media, Alarm, Notification은 제법 눈에 익습니다.

플랫폼에 이미 탑재되어 여기저기서 사용하고 있는 세션들이라 그렇겠지요.

위의 세 세션은 이전 볼륨 포스트에서도 나왔습니다.


SOUND_TYPE_MEDIA
Sound type for media

SOUND_TYPE_ALARM
Sound type for alarm

SOUND_TYPE_NOTIFICATION
Sound type for notifications


미디어나 알람은 누구나 세션을 열어서 사용할 수 있고,

더불어 해당 세션을 위한 볼륨도 조절할 수 있습니다.

노티를 위한 세션은 통상 시스템 레벨의 앱에서 알림을 목적으로 사용합니다.

외부 개발자들도 알림을 목적으로만 사용하는게 좋겠네요.


Emergency는 어느 세션보다 우선하여 동작하는 세션입니다.

Emergency 세션 위로 다른 세션이 포개질 수 없습니다.

Emergency는 silent도 되지 않기 때문에 함부로 사용하면 안되겠죠?


VoIP는 Voice Over IP를 위해 새롭게 추가된 세션입니다.

볼륨에도 아래와 같이 VOIP를 위한 타입이 추가된 상태입니다.


SOUND_TYPE_VOIP
Sound type for voip (Since 2.4)


VoIP를 위한 세션까지 구비되어 있으니,

VoIP 서비스 업체들은 어서 타이젠으로 조인해주세요 :)

그외에 볼륨 타입에는 존재하지만 세션에는 노출되지 않은 세션이 있습니다.


SOUND_TYPE_SYSTEM
Sound type for system

SOUND_TYPE_RINGTONE
Sound type for ringtones (Since 2.4)

SOUND_TYPE_CALL
Sound type for call (Since 2.4)

SOUND_TYPE_VOICE
Sound type for voice


위의 세션을 살펴보면 몇가지 알 수 있는 사실이 있습니다.

요금 과금과 직접적으로 관련된 Call 기능은 3rd party가 개발할 수 없다는 것이지요.

사용자 '돈'과 직접적으로 만나는 부분은 아무래도 조심스럽습니다.

단순히 기존 아키텍쳐를 바꾸고 몇몇 API만 공개한다고 될 수준은 아닙니다.


그리고 System 세션은 3rd party에게 열 이유가 없습니다.

System은 플랫폼에서 독점적으로 사용하고 있습니다.

외부에서는 볼륨을 조절하는 것으로 만족해야겠네요.


클락앱의 알람을 설정하는 코드를 살짝 엿보겠습니다.

static bool ring_app_create(void *data)
{
    retvm_if(!data, FALSE, "data null");
    int nErr = SUCCESS;
    struct appdata *ad = (struct appdata *)data;

    ad->is_create = EINA_FALSE;
    nErr = alarmdb_init(NULL);
    retvm_if(SUCCESS != nErr, FALSE, "alarmdb_init failed! return=%d\n",
         nErr);
    nErr = alarmmgr_init(PKGNAME);
    retvm_if(SUCCESS != nErr, FALSE, "alarmmgr_init failed! return=%d", nErr);
    //mm
    sound_manager_set_session_type(SOUND_SESSION_TYPE_ALARM);
    // 
    ring_util_state_get(ad);
    nErr = alarmmgr_set_cb(_ring_mgr_cb_func, ad);
    retvm_if(SUCCESS != nErr, FALSE, "alarmmgr_set_cb failed! return=%d", nErr);
    ad->motion_sensor_handle = -1;
    //_ring_init_motion_sensor(ad);
    return TRUE;
}


클락앱은 알람을 설정할 수 있는 기능이 있는데요,

알람을 설정할 때 sound_manager_set_session_type()을 이용하여 세션을 설정합니다.


Media session은 sound_manager_set_media_session_option()을 이용하여,

- 미디어 세션 시작시 다른 세션과 Mix할 것인지 다른 세션을 Pause시킬지

- 미디어 세션 플레이 중에 인터럽트를 허용할 것인지

두가지 옵션을 설정할 수 있도록 준비되어 있습니다.

아래의 enum을 참고하시면 보다 명확하게 이해하실 수 있을겁니다.



보통은 하나의 API가 하나의 옵션을 지정하게 되어있는데요,

Session 옵션을 지정하는 API는 두가지 옵션을 지정하게 되어있습니다.

Media session의 옵션을 모두 다루려고 그렇게 설계한 것일까요?



하지만, 안타깝게도 media session 옵션용 API가 하나 더 생겨납니다.

위의 enum은 sound_manager_set_media_session_resumption_option()에서 사용합니다.

Resumption option은 Media 세션이 다른 세션에 의해 중지되었을때 Resume 정책을 지정합니다.

- 시스템 정책에 따라 세션을 resume하거나

- 시스템 정책 + 이 세션을 중지한 미디어 세션이 중지될 때

위의 두가지 정책 중에 하나를 선택할 수 있습니다.


미디어 세션은 여타의 세션들 중에 우선순위가 가장 낮은 부류에 속하기 때문에,

다른 세션들에 의해 쉽게 interrupt 될 수 있습니다.

그래서 resume에 대한 부분도 미리 고려해줄 필요가 있습니다.


sound_manager_set_session_interrupted_cb() 함수로 인터럽트 상황을 통제할 수 있습니다.

우선 인터럽트 상황을 처리할 콜백함수를 위의 함수로 등록해줍니다.

그리고 인터럽트 상황이 발생하면 콜백함수가 불리면서 아래 enum 값을 콜백함수로 넘겨줍니다.


각각의 인터럽트 상황에 맞게 동작을 처리해줍니다.

미디어를 재생하고 있는데 헤드폰이 뽑혔다면 어떻게 해야할까요?

일반적으로는 재생이 중지됩니다. :)


Sound manager의 세션은 이 정도로 정리하도록 하겠습니다.

다음 포스팅에서는 sound의 다른 부분을 살펴보도록 하겠습니다.


그럼 좋은 하루 보내세요~

끝_



* References

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__SOUND__MANAGER__SESSION__MODULE.html



안녕하세요, 타이젠 개발자 윤진입니다.


앱 개발을 하려면, 플랫폼에서 제공하는 다양한 요소를 사용해야합니다.

앞으로 몇 개의 포스팅에 걸쳐서 '소리'와 관련된 부분을 다뤄보도록 하겠습니다.

첫 포스팅에서는 가볍게 워밍업 하는 기분으로 '볼륨'을 이야기해보죠.


2015년 11월 현재,

Tizen 2.4가 최신 버전이기 때문에, 2.4를 기준으로 설명하겠습니다.

Tizen 2.4가 올라간 타겟은 두 대가 있는데요,

- 지난 10월에 인도에서 출시된 Z3

- 타이젠 데브랩 행사에서 사용하고 있는 TM1

필요하면 위의 타겟들과 에뮬레이터를 이용하여 포스팅하도록 하겠습니다.


볼륨 API를 살펴보기에 앞서 Z3에 올라가 있는 볼륨 앱을 실행해보도록 해보죠.

근데... Z3를 어디에 뒀는지 통 찾을 수가 없네요;

우선 Tizen 2.4 에뮬을 띄워 볼륨앱을 실행해보도록 하겠습니다;



볼륨앱은 단순하며 직관적으로 조작할 수 있는 UI를 가지고 있습니다.

하드키인 볼륨키나 화면의 슬라이더를 이용하여 볼륨을 조절할 수 있도록 지원합니다.

플랫폼에서는 볼륨앱이 volume API를 가장 적극적으로 사용하고 있겠죠?


Volume API


2.4 기준으로 외부에 노출되어 있는 볼륨 API는 위의 8개 뿐입니다.

볼륨 조작을 위해서는 사운드 타입정도만 인지하면 되기때문에 API가 단촐합니다.

실제 볼륨앱 소스를 보면서 위의 API가 어떤 식으로 활용되고 있는지 보겠습니다.


볼륨앱의 소스는 당연히 공개되어 있는데요,

공개된 소스가 플랫폼 2.4 소스와 완벽하게 일치하진 않겠지만(계속 진화하고 있으므로),

volume을 제어하는 control 루틴을 변화가 적으니 그 코드를 그대로 봐도 괜찮을겁니다.

볼륨 소스를 git으로 다운로드 받으시려면 아래 repo.를 이용하세요.

repo. : git://review.tizen.org/apps/core/preloaded/volume-app

branch : tizen


볼륨앱에는 하나의 슬라이더가 나오는데요,

볼륨앱을 실행하는 시점에 활성화된 볼륨타입을 가져와서 화면에 보여줍니다.



sound_manager_get_current_sound_type()으로 활성화되어 있는 사운드 타입을 가져오면,

바로 위에 명시된 8개의 enum 값 중 하나를 얻어올 수 있습니다.

2.4에는 ringtones, call, voip와 같이 콜과 관련된 사운드 타입이 추가되었죠.

타이젠 플랫폼이 3rd party를 위해 call 관련 API, 특히 VoIP를 정비하고 있나보네요.


sound_type_e volume_sound_sound_manager_type_get(void)
{
    int ret = 0;
    sound_type_e sound_type = -1;

    ret = sound_manager_get_current_sound_type(&sound_type);
    _D("ret: %d, sound type: %d", ret, sound_type);
    switch (ret) {
    case SOUND_MANAGER_ERROR_NONE:
        _D("Error none");
        break;
    case SOUND_MANAGER_ERROR_NO_PLAYING_SOUND:
        _D("NO playing sound");
        sound_type = SOUND_TYPE_RINGTONE;
        break;
    default:
        _E("Failed to get sound type : %d", ret);
        sound_type = SOUND_TYPE_RINGTONE;
        return sound_type;
    }  

    if(sound_type == SOUND_TYPE_SYSTEM)
        sound_type = SOUND_TYPE_RINGTONE;

    return sound_type;
}


볼륨앱에서는 ringtones를 기본으로 설정하고 있습니다.

사용자가 홈화면에서 볼륨키를 누르면 링톤의 음량을 조절할 수 있겠네요.


그리고 sound_manager_get_max_volume()과 sound_manager_get_volume()을 이용하여,

슬라이더의 단계와 활성화된 영역을 표시합니다.


int volume_sound_sound_manager_step_get(sound_type_e type)
{
    _D("volume sound manager step get");
    int ret = -1, step = 0;

    ret = sound_manager_get_max_volume(type, &step);
    retvm_if(ret < 0, -1, "Failed to get step");

    sound_info.sound_step = step;

    return step;
}

int volume_sound_sound_manager_volume_get(sound_type_e type)
{
    int ret = -1, val = 0;
    ret = sound_manager_get_volume(type, &val);
    retvm_if(ret < 0, -1, "Failed to get volume");
    return val;
}


위의 volume_sound_sound_manager_step_get()에서,

sound_manager_get_max_volume()을 이용하여 전체 단계를 얻고 있네요.

그리고 volume_sound_sound_manager_volume_get()에서,

sound_manager_get_volume()으로 현재 단계를 얻고 있습니다.


그리고 sound_manager_set_volume()으로 현재 설정된 사운드 타입의 볼륨을 조절합니다.

sound_manager_set_volume_changed_cb()으로 등록한 콜백에서는 볼륨이 변할때마다,

화면을 다시 그리고 볼륨값을 관리하고 있네요.

이 부분 소스는 따로 언급하지 않겠습니다.


사실 sound manager의 볼륨 API에는 낯선 함수가 하나 있습니다.

sound_manager_unset_current_sound_type() 함수인데요,

이 함수는 sound_manager_set_current_sound_type()과 짝을 이루는 함수입니다.

set이 있으니 당연히 unset도 존재하는 것이지요.

하지만, 플랫폼에서는 위 함수를 사용하는 부분을 찾지 못했습니다.


볼륨앱의 경우,

sound_manager_get_current_sound_type()으로 현재 사운드타입을 얻어서 볼륨을 조절하는데요,

위의 unset 함수를 누군가 사용한다면 current sound type을 못 가져오겠지요.

물론 볼륨앱은 예외처리는 되어 있습니다만,

실제 유저시나리오 중에 unset이 필요한 경우가 있는지 모르겠습니다.

볼륨키를 컨트롤하려면 어느 상황에서나 사운드타입이 결정되어 있어야 하지 않나 싶기도 하네요.

(이 부분은 제 지식이 짧아서 좀 더 알아봐야겠습니다)


이것으로 볼륨 관련 포스팅은 마치겠습니다.

다음 포스팅은 좀 더 흥미로운 부분을 다뤄보도록 하겠습니다.


그럼 좋은 하루 보내세요~

끝_


* References

https://developer.tizen.org/dev-guide/2.4.0/org.tizen.native.mobile.apireference/group__CAPI__MEDIA__SOUND__MANAGER__VOLUME__MODULE.html

https://developer.tizen.org/community/code-snippet/native-code-snippet/set-volume-level?tab=all

https://developer.tizen.org/community/code-snippet/native-code-snippet/track-volume-changes?tab=all

https://developer.tizen.org/community/code-snippet/native-code-snippet/get-maximum-volume-level-given-sound-type.?tab=all

https://developer.tizen.org/community/code-snippet/native-code-snippet/get-current-volume-level?tab=all

+ Recent posts