2010-11-24

mediaplayerを作ってみる(2)

そういえば、一応目標を。と言うか、理想の完成形を。

1・・・SDカードのいくつかのディレクトリから音楽ファイルを読み込む。
2・・・ListViewに表示する。
3・・・ListViewをタッチすると音楽が聴ける。
4・・・ディレクトリ内で連続再生 。
5・・・ディレクトリをまたいで連続再生。
6・・・ランダム再生。

こんな感じ。

前回のでは、曲が終わると止まってしまう。
まず、これを何とかしようと。ここなどを参考に。(ちょっと下の方)

OnCompletionListenerとやらで、何とかなりそう。
 変更点だけ書いていきます。

フィールドの
private static int num = 0; を private int musicNum; に
なんかこの方が良さそうなので。

implementsに MediaPlayer.OnCompletionListener を追加。

//mpの生成 のとこを

mp = new MediaPlayer();
mp.setOnCompletionListener(this); //ここと
musicNum = 0; //ここを追加

で、一番下に

     public void onCompletion(MediaPlayer mp) {
        if (++musicNum < musicList.size()) playMusic();
        else {
            musicNum = 0;
            playMusic();
        } 
    }

を追加。
で、このままだと1曲終わるまで動きが確認できないのでボタンを1つ追加。

    <Button
        android:id="@+id/skip_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/skip_button">
    </Button>

ボタンのテキストをstringに追加。

    <string name="skip_button">skip</string>

なんか英語。あってるんだろうか。英語力がないのが残念。

で、↓を追加。他のボタンの下あたりに適当に。

btnSkip = (Button)findViewById(R.id.skip_button);
btnSkip.setOnClickListener(this);

この書き方でなく、ここを参考にして書き直したほうがいいかも。
僕は、まあ、そのうち。

それと、ボタンイベントを追加。btnStopの次に。(else ifの { の閉じた後)

} else if (view == btnSkip) {
                int duration = mp.getDuration();
                mp.seekTo(duration - 3000);
}

 これで、残り3秒まで飛びます。続けて再生してるか確認しやすい。
最近気づきました。

実は一度、完成形間近まで作ったんですが、コードが読みにくいし、
ちょっと行き詰まったので、ここに書きながら作り直してます。

まあ、それはそれで動いてるんですが。あまり色々操作をしなければ。
例の8円運用 is01に 取り込んでみて、今もそれで音楽を聴いてます。

でもねー、なんかねー、と言う感じなんですわ。色々と。
なので、あせらず急がず。ちょとづつ。なるべく、読みやすく。

いつか、完成するんだろうか。しないかも。
まあ、それはそれで。

2010-11-22

mediaplayerを作ってみる(1)

SDカードのファイルを再生する

作っています。少しづつ。まあ、どこまでいけるか分かりませんが。
とりあえず、貼っときます。

xmlから。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <Button
        android:id="@+id/start_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/start_button">
    </Button>
    <Button
        android:id="@+id/stop_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/stop_button">
    </Button>
</LinearLayout>

ボタンが二つだけ。一応string.xmlも使ってみました。

 <?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello World, SDMediaPlayerActivity!</string>
    <string name="app_name">SDMP</string>
    <string name="start_button">再生 / 次へ</string>
    <string name="stop_button">停止</string>
</resources>

 HelloWorld消すの忘れてました。

 で、Activity。

package net.asasvata.sdmediaplayer;

import java.util.ArrayList;

import android.app.Activity;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;

public class SDMediaPlayerActivity extends Activity
    implements View.OnClickListener {
   
    //フィールド
    private static int num = 0;//次の曲に進む用

    private MediaPlayer mp;
   
    private ArrayList<String> musicList;
   
    private Button btnStart;
    private Button btnStop;
       
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        //mpの生成
        mp = new MediaPlayer();
       
        //musicListの生成と曲の追加
        musicList = new ArrayList<String>();
        musicList.add("leavetheworldbehind.mp3");
        musicList.add("onlygirl.mp3");
        musicList.add("richgirl.mp3");
        musicList.add("rudeboy.mp3");
        musicList.add("yeahyeah.mp3");
       
        //ボタンの取得
        btnStart = (Button)findViewById(R.id.start_button);
        btnStop = (Button)findViewById(R.id.stop_button);
       
        //OnClickListenerのセット
        btnStart.setOnClickListener(this);
        btnStop.setOnClickListener(this);
    }
    //ボタンが押されたときの処理
    public void onClick(View view) {
        if (mp.isPlaying()) {
            if (view == btnStart) {
                if (++num < musicList.size()) {
                   
                    playMusic();
               
                } else {
                    num = 0;
                    playMusic();
                }
            } else if (view == btnStop) {
                mp.stop();
                try {
                    mp.prepare();
                } catch (Exception e){
                }
            }
        } else {
            if (view == btnStart) {
               
                playMusic();
            }
        }
    }
   
    public void playMusic() {
        mp.reset();
        try{
            mp.setDataSource(Environment.getExternalStorageDirectory().getPath()
                    + "/" + musicList.get(num));
            mp.prepare();
            mp.seekTo(0);
            mp.start();
        } catch (Exception e) {
        }
    }
}

Environment.getExternalStorageDirectory().getPath()
↑で、SDのパスが得られるようです。"/sdcard"でもいける様ですが。
こっちの方が確実みたいなので。

ボタンを押したときの動きは見たままです。
とりあえず、sdの音楽は再生できます。
エミュレーターのsdにファイルを入れるやり方はここを参考に。
sdのパスの取りかたも。

なんか疲れました。

2010-11-20

自作Viewをレイアウトに追加

seesaaから、移動。

自作Viewの貼り付けについては、ここを参考に。
で、本に乗ってたのを改造したのを。長いですが。

SurfaceViewなんですが、ここを見ると一手間要るようです。
が、なぜか動きます。Viewと同じやり方で。何かの参考になればいいですが。

 とりあえず、xmlから。色とか文字はstring.xmlで管理するようですが
それは、まあ、そのうちに。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        >
           <ImageView
            android:id="@+id/imageView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
        />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#00c608"
            android:textSize="12sp"
            android:text="適当にボタンを押してください\n数字はフォントサイズです"
            android:layout_weight="2"
        />
    </LinearLayout>
    <net.asasvata.SampleSurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
    />
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        >
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="start"
        />
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="stop"
        />
    </LinearLayout>
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:background="#00000000"
        >
        <RadioGroup
            android:id="@+id/radioGroup"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_weight="1"
            >
            <RadioButton
                android:id="@+id/radioButton0"
                android:text="H"
                android:textColor="#00c608"
               />
             <RadioButton
                android:id="@+id/radioButton1"
                android:text="M"
                android:textColor="#00c608"
               />
               <RadioButton
                android:id="@+id/radioButton2"
                android:text="L"
                android:textColor="#00c608"
               />
        </RadioGroup>
    </LinearLayout>
</LinearLayout>

パッケージ名とファイル名を指定。あとは同じようなやり方。
次は、SurfaceViewを。

package net.asasvata;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet; //これが重要みたいです。
import android.view.*;
//サーフェイスビューの利用
public class SampleSurfaceView extends SurfaceView     
           implements   SurfaceHolder.Callback,Runnable {

 private SurfaceHolder holder;//サーフェイスホルダー
    private Thread thread;        //スレッド

    private int px = 0;//X座標
    private int py = 5;//Y座標
    private int vx = 0;//X速度
    private int vy = 0;//Y座標
    //コンストラクタ
    public SampleSurfaceView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //サーフェイスホルダーの生成
        holder = getHolder();
        holder.addCallback(this);
        holder.setFixedSize(getWidth(), getHeight());
    }
    //フィールドをprivateにしてみたので、ゲッター&セッター
    public int getVx() {
        return vx;
    }
    public int getVy() {
        return vy;
    }
    public void setVx(int vx) {
        this.vx = vx;
    }
    public void setVy(int vy) {
        this.vy = vy;
    }
    //サーフェイスの生成
    public void surfaceCreated(SurfaceHolder holder) {
        
        //スレッドの開始
        thread = new Thread(this);
        thread.start();
    }
    //サーフェイスの変更
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    }
    //サーフェイスの破棄
    public void surfaceDestroyed(SurfaceHolder holder) {
        thread = null;
    }
    //スレッドの処理
    public void run() {
        int i = 5;

        Paint paint = new Paint();
        paint.setTextSize(i);
        Canvas canvas;
        int j=0, k=0, l = 0;

        while(thread != null) {
            //ダブルバッファリング
            String str = ""+i;
            paint.setTextSize(i);
            paint.setColor(Color.rgb(255-j, 255-k, 255-l));
            canvas = holder.lockCanvas();
            canvas.drawColor(Color.argb(255, j, k, l));
            canvas.drawText(str, px, py, paint);
            holder.unlockCanvasAndPost(canvas);
            //移動
            if (vx > 0) {
                //文字サイズに合わせて跳ね返る位置を調整
                if (getWidth()-paint.measureText(str)< px){
                    vx = -vx;
                    i += 5; j += 10; k += 20; l += 30;
                    if (i > 101) i = 5;
                    if (j > 255) j = 0;
                    if (k > 255) k = 0;
                    if (l > 255) l = 0;
                }
            } else {
                if (px < 0) {
                    vx = -vx;
                    i += 5; j += 10; k += 20; l += 30;
                    if (i > 101) i = 5;
                    if (j > 255) j = 0;
                    if (k > 255) k = 0;
                    if (l > 255) l = 0;
                }
            }
            if (vy < 0) {
                //フォントサイズに合わせて跳ね返る位置を調整・・・のはずなんですが。
                if (py < i) vy = -vy;
            } else {
                if (getHeight()< py) vy = -vy;
            }
            px += vx;
            py += vy;
            //スリープ
            try {
                Thread.sleep(50);
            } catch (Exception e) {
            }
        }
    }
}

次は、Activity。

 package net.asasvata;

import android.app.Activity;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RadioGroup;

//サーフェイスビュー、テキストビュー、ボタン、ラジオボタンを使います
public class SampleActivity extends Activity implements View.OnClickListener {
   
    SampleSurfaceView sv;
    private Button button1, button2;
    private RadioGroup radioGroup;
  
    int num = 1;//ボタンを押したときの状態保持のために使います
    int sp = 0;//移動速度を変更するために使います
  
    //アプリの初期化
    @Override
    public void onCreate(Bundle icicle) {      
        super.onCreate(icicle);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
      
        ImageView imageView = (ImageView)findViewById(R.id.imageView);
        imageView.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
      
        sv = (SampleSurfaceView)findViewById(R.id.surfaceView);
      
        button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(this);
      
        button2 = (Button)findViewById(R.id.button2);
        button2.setOnClickListener(this);
      
        radioGroup =(RadioGroup)findViewById(R.id.radioGroup);
        radioGroup.check(R.id.radioButton1);
    }
  
    //ボタンとラジオボタンがクリックされたときの処理
    public void onClick(View view) {
      
        //ラジオボタンが押されたときの処理
        switch (radioGroup.getCheckedRadioButtonId()) {
        //ラジオボタンのidによって処理を変えます
        case R.id.radioButton0:
            sp = 14;
            //ラジオボタンが押されたときの速度方向を維持します
            keepSpDir(sv);
            break;
        case R.id.radioButton1:
            sp = 7;
            keepSpDir(sv);
            break;
        case R.id.radioButton2:
            sp = 3;
            keepSpDir(sv);
            break;
        }
      
        //ボタンがクリックされたときの処理
        if (view == button1) {
            //button1が連続して押されたとき何もしないようにしてます
            if (num == 0) {
            } else {
                //button2が押されたときのnumの値で処理を変えます
                switch (num) {
                case 1:
                    //速度方向の維持
                    sv.setVx(sp); sv.setVy(sp);
                    num = 0;//これで連続して押されたときの処理につなげます
                    break;
                case 2:
                    sv.setVx(-sp); sv.setVy(sp);
                    num = 0;
                    break;
                case 3:
                    sv.setVx(sp); sv.setVy(-sp);
                    num = 0;
                    break;
                case 4:
                    sv.setVx(-sp); sv.setVy(-sp);
                    num = 0;
                    break;
                }
            }
        } else if (view == button2) {
            //button2が押された時点での速度方向によってnumの値を変えます
            if (sv.getVx()>0 && sv.getVy()>0) {
                sv.setVx(0); sv.setVy(0);
                num = 1;
            } else if (sv.getVx()<0 && sv.getVy() >0) {
                sv.setVx(0); sv.setVy(0);
                num = 2;
            } else if (sv.getVx()>0 && sv.getVy() <0) {
                sv.setVx(0); sv.setVy(0);
                num = 3;
            } else if (sv.getVx()<0 && sv.getVy()<0) {
                sv.setVx(0); sv.setVy(0);
                num = 4;
            }
        }
    }
  
    private void keepSpDir(SampleSurfaceView sv) {
      
        if (sv.getVx()>0 && sv.getVy()>0) {
            sv.setVx(sp); sv.setVy(sp);
        } else if (sv.getVx()<0 && sv.getVy() >0) {
            sv.setVx(-sp); sv.setVy(sp);
        } else if (sv.getVx()>0 && sv.getVy() <0) {
            sv.setVx(sp); sv.setVy(-sp);
        } else if (sv.getVx()<0 && sv.getVy()<0) {
            sv.setVx(-sp); sv.setVy(-sp);
        } else {
            sv.setVx(sp); sv.setVy(sp);
        }
    }
}

 なんかよく分からないままに改造したんで、おかしなとこもあるかも。
まあ、だいたいで。

ここだと、貼り付けたときもインデントが残る・・・。
初めからここで書いとけばよかった。

2010-11-08

Ubuntuでラジオ(2)

録音したmp3ファイルの加工をしてみた。

と言ってもそんな大したことをする分けでなく、以前と同じ。
余分なとこを切ってフェードインorアウト。
mp3DirectCutはwineで動くようですが、なるべく使わない方向で。

ふらふらした結果、Audacity。Ubuntuソフトウェアセンターから。
mp3で書き出そうとすると、lameを入れろといってきまして。
指示にしたがったんですが、入れられず。アンインストール。

違うソフトをインストールして、その時一緒にlameもインストール。
そのソフトが使いにくいのでアンインストール。
Audacity再挑戦。今度は、端末で。

sudo apt-get install audacity lame

すると、lameは最新です、と。
ええんかな、と思いながらもmp3で書き出そうとしたら、
すんなりといきました。なんか、よく分かりません。

それはそれとして、使い方で、つまずいたとこがあったのでメモを。

ファイルを開くとこんな感じ。とりあえず、画面の縦方向を広げた方が
無難かも。まあ、お好みで。














表示→元の縮尺に戻す。で、こんな感じ。
加工したいとこにカーソルを合わせてドラッグ。
写真だとマウスポインタになってますが、" I " ←こんなのになります。














こんな感じになる。で、この範囲を切り取るなり、フェードするなり。
トリミングは、この範囲が残ります。
フェードはエフェクトから。なんか不思議な機能もありますが。エンベロープツール。
エフェクトにある方が簡単ですが、まあ、お好みで。














で、何につまずいてたか。選択を上に出てくる三角マークでやろうとしてました。
 それもドラッグできるんで。色も変わるし。
何なのかは未だに分かりません。まあいいんですが。

それから、音量の調整はmp3Gainが使えます。
Audacityで出来ると思いますが。 多分。

2010-11-03

Ubuntuでradio

Ubuntuでラジオを録音してみた。

探したらありました。streamripper。shoutcastを録音できます。
ファイルも分割してくれます。有名なんですね。winでも使えます。

単体では動かないようで、streamtuner か、Tunapieが必要です。
 winだとwinamp。

streamtunerがちゃんと動かないので、Tunapieで。
Ubuntuソフトウェアセンターからか、端末を使って、
sudo apt-get install tunapie  多分。

streamripperは、
sudo apt-get install streamripper

なんですが、既に最新ですと言われました。
Tunapieについてるのか、streamtunerと一緒にダウンロードしたのが
残ってたのか。アンインストールしたんですが。streamtuner。

まあ、録音できてますから。とりあえずメモをつけときます。

起動するとこんな感じ 。左のリストに聴きたい局がないときは、
shoutcastのホームページにいって、













 右上の枠内で右クリック。













赤くなってるとこをクリック 。ウィンドウがでます。
shoutcastで局を探せたら








 ウィンドウ内のURLにドラッグ&ドロップ。
NameとBitrateを入力。Bitrateは、shoutcastの右の方に書いてあります。
Genreも。僕は、書いてませんが。










OKすると追加されます。













選択して、プレイ。プレイヤーが立ち上がります。
時間かかります。結構。






録音はTunapieのボタンで。

 録音先はデフォルトで、ホームフォルダないの隠しフォルダになってます。
Ctrl+Hで表示できます。この画像では変えてますが。
TunapieのFile→Preferencesで開きます。Browseで変えてください。













Audio playerに設定されているaudaciousはいつインストールしたのか覚えてません。
まあいいんですが。

audaciousでラジオをプレイリストに追加するには、設定→再生で
Clear current・・・のチェックを外しておくと、いいみたいです。
Tunapieで選んで再生を繰り返すと、リストができます。
何かいっぱいでてくるときもありますが、消してます。僕は。

リストの保存は、プレイリスト→Export Playlist・・・で。
録音するのに3つも立ち上がります。そんな感じです。