컴퓨터를 포맷을 해서 알송을 다시 설치하려고 사이트에 가니까 2.0이 새로 나왔더군요. 아직 2.0Beata여서 자동업그레이드를 제공하지 않았던 것이군요.
국내 MP3플레이어 중에서는 최고라고 생각하고 있는 알송! 왜냐하면 사용자가 많아서 인지 가사가 다 잘나오거든요^^ 가사는 사용자가 직접 등록하는 것인데, 신기하게도 희귀한 음악 빼곤 왠만해선 가사가 다 입력이 되어있습니다^^ 사용자가 많으니 이런 점이 참 좋죠^^ 게다가 플레이어 기능도 전혀 불편하지가 않죠. 전 그래서 알송을 애용해요~ ^^

2.0에서 새로 생긴 기능을 한번 살펴봅시다.
모양은 아래와 같이 바뀌었군요.
사용자 삽입 이미지
스크린샷을 보면 알송으로 무엇을 할 수 있는지가 한눈에 보이네요. 게다가 mp3파일에 앨범커버가 있으면 커버도 보여주네요^^ 앨범커버를 보여줘야 역시 뭔가 간지가 나죠-_-

1. 아이튠즈와 비슷한 기능중 하나인 재생목록기능
이건 자신만의 재생목록을 만들 수 있습니다. 새 재생목록 추가버튼 클릭하고, 새로운 재생목록을 만들어서 음원을 추가하면 재생목록을 만들 수 있습니다. 재생목록을 분리해서 정리해놓으면 듣고 싶을 때 노래도 쉽게 찾을 수 있겠죠.
게다가 추가로 많이 들은 음악, 최근 들은 음악을 제공합니다. 많이 들은 음악은 알송으로 재생한 곡수를 통계를 내어서 가장 많이 들었던 노래를 순위별로 보여주죠. 아이튠즈에 있던 기능들이죠^^
사용자 삽입 이미지

재생목록 관리 화면


2. MP3플레이어와 직접적인 연동
여기서 말하는 MP3플레이어는 알송이 아닌 기기를 말합니다-_- 제가 가지고 있는 s9와 연결해보겠습니다.
연결하면 신기하게 인식을 하는군요^^
사실 이 기능은 뭐 그냥 자신의 하드드라이브에 있는 곡들을 MP3Player로 이동식디스크로 복사하는 건데, 좀 더 편하게 현재 재생되고 있는 노래나 재생목록에 있는 곡들을 쉽게 복사할 수 있죠^^
사용자 삽입 이미지

MP3남은 용량도 볼 수 있네요.

아 기존부터 벨소리 만들기 기능이 있었는데요. 벨소리 사는 것도 있네요. 만드는 것과 벨소리 파는 것을 공존시키다니-_- 뭐 해당 음원이 없으면, 구입할 수도 있겠네요^^
사운드효과는 뭐 제가 막귀여서 이런 기능은 저한테 사치죠-_-

디자인도 깔끔하고 맘에 드네요 하지만 이런 기능들은 다 필요없고-_- 알송을 쓰는 이유는 단하나입니다-_-
싱크가사죠-_- 방대한 양의 싱크가사가 존재합니다. 몇백만 되는 사용자들의 노가다 정성이 들어간 멋진 기능이죠. 이 기능때문에 알송을 포기할 수 없어요-_-

 
Posted by 머드초보
,
 
이건뭐....프레임워크를 왜 쓴거지-_-;
소스코드만 더 길어졌네.
어쨌든 저의 삽질의 결정체를 공개할랍니다-_-; 나름 열심히 만든거라...ㅠㅠ
보시면 이것저것 신경을 많이 쓴걸(?) 볼 수 있을겁니다-_-;
타이머의 zerofill...-_-;
이걸 분석하면 Mate Flex Framework에서 제공하는 Injector에 대해서 이해하실 수 있을겁니다.

invalid-file

소스파일입니다.

아래에 INSTALL NOW클릭하시면 설치가 될 겁니다.
설치가 안되신다면 http://www.adobe.com/go/getair/ 여기서 AIR를 다운로드하세요.

Alternative content

Get Adobe Flash player

 
Posted by 머드초보
,
 

AIR로 사운드 재생이 가능한 것을 알았습니다-_-;
초초초초초간단한 MP3플레이어를 만들어봤습니다.
사운드 컨트롤하기 참 쉽게 되어있군요.

아래는 대략 소스입니다.
[code]
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
 layout="absolute" width="400" height="300" viewSourceURL="srcview/index.html">

 <mx:Script>
  <![CDATA[
   import mx.controls.Alert;
   
   private var file:File = new File();
   private var req:URLRequest;
   private var sound:Sound;
   private var channel:SoundChannel;
   private var pausePosition:int;
   
   public function findFile():void {
    try {
     file.addEventListener(Event.SELECT, selectFileHandler);
     file.browse();
    } catch (error:Error) {
     Alert.show("파일열기 실패했습니다.");    
    }
   }
   
   public function selectFileHandler(event:Event):void {
    if (channel != null) {
     channel.stop();
    }
    sound = new Sound();
    sound.addEventListener(Event.COMPLETE, onSoundLoaded);
    sound.addEventListener(ProgressEvent.PROGRESS, onLoadProgress);
    sound.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
   
    pausePosition = 0;
    textFileName.text = event.currentTarget.nativePath;
    sound.load(new URLRequest(event.currentTarget.nativePath));
    btnPlay.enabled = true;
   }
   
   public function onLoadProgress(event:ProgressEvent):void {
       var loadedPct:Number = Math.round(100 * (event.bytesLoaded / event.bytesTotal));
       trace("The sound is " + loadedPct + "% loaded.");
     fileLoadingPB.setProgress(loadedPct, 100);  
   }
   
   public function onSoundLoaded(event:Event):void {
    var localSound:Sound = event.target as Sound;
    textArtist.text = localSound.id3.artist;
    textSongName.text = localSound.id3.songName;
   }
   
   public function onIOError(event:IOErrorEvent):void {
    Alert.show("The sound could not be loaded: " + event.text);
       trace("The sound could not be loaded: " + event.text);
   }
   
   public function btnPlayClickHandler(event:Event):void {
    btnPlay.enabled = false;
    btnStop.enabled = true;
    channel = sound.play(pausePosition);
    addEventListener(Event.ENTER_FRAME, onEnterFrame);
    channel.addEventListener(Event.SOUND_COMPLETE, onPlaybackComplete);  
   }
   
   private function onEnterFrame(event:Event):void {
    var estimatedLength:int =
           Math.ceil(sound.length / (sound.bytesLoaded / sound.bytesTotal));
       var playbackPercent:uint =
           Math.round(100 * (channel.position / estimatedLength));
          playPB.setProgress(playbackPercent, 100);
       trace("Sound playback is " + playbackPercent + "% complete.");
   }
   
   private function onPlaybackComplete(event:Event):void {
    btnPlay.enabled = false;
    btnStop.enabled = false;
    trace("The sound has finished playing.");
       removeEventListener(Event.ENTER_FRAME, onEnterFrame);
   }
   
   public function btnStopClickHandler(event:Event):void {
    btnPlay.enabled = true;
    btnStop.enabled = false;
    pausePosition = channel.position;
    channel.stop();
   }
   
  ]]>
 </mx:Script>
 <mx:ProgressBar id="fileLoadingPB" x="125.5" y="160" mode="manual"/>
 <mx:ProgressBar id="playPB" x="125.5" y="196" mode="manual" label="PLAYING %1%"/>
 <mx:Label x="72.5" y="196" text="재생바" height="28" width="45" textAlign="right"/>
 <mx:Label x="72.5" y="160" text="파일읽기" height="28" textAlign="right"/>
 <mx:Label x="82.5" y="35" text="제목 :" width="44" textAlign="right"/>
 <mx:Label x="82.5" y="61" text="가수명 :" textAlign="right"/>
 <mx:Label x="82.5" y="87" text="파일명 :" textAlign="right"/>
 <mx:Button id="btnPlay" x="91.5" y="248" label="플레이" click="btnPlayClickHandler(event);" enabled="false"/>
 <mx:Button id="btnStop" x="158.5" y="248" label="일시정지" click="btnStopClickHandler(event);" enabled="false"/>
 <mx:Button x="236.5" y="248" label="파일열기" click="findFile();"/>
 <mx:Text id="textSongName" x="134.5" y="35" text="KHJ 바보" width="191"/>
 <mx:Text id="textArtist" x="134.5" y="61" text="KHJ 돼지" width="191"/>
 <mx:Text id="textFileName" x="134.5" y="87" text="KHJ 멍충이" width="191"/>
 
</mx:WindowedApplication>
[/code]
소스를 보면 그리 어렵지 않습니다.
Sound라는 클래스가 있습니다.
사운드객체를 하나 선언하고, 파일명으로 URLRequest를 이용해 객체를 생성해서 그걸 Sound객체의 load메소드를 통해서 로드를 한 다음에, play만 해주면됩니다.

게다가 이것저것 자체적으로 지원해주는게 많습니다. 일시정지를 할 수 있게 stop을 하기전에 channal이라는 클래스를 통해 현재 position을 얻어오면 stop한다음에 그 포지션으로부터 다시 시작할 수 있습니다.

재생완료시 이벤트를 추가할 수 있고, 파일이 로드될 때 이벤트 등의 이벤트를 지원하는군요.

PS. AIR로 MP3플레이어만들면 더 멋있을 것 같은데-_-;

 
Posted by 머드초보
,