Rhythmboxで1曲ループを実現する −3−

今回は1曲ループのための関数を実装します。

 

簡単に説明すると、

リニア再生(順番通りに再生するヤツ)の関数内で次の曲/前の曲へ飛ぶとき、代わりに今再生している曲へ飛ばしちゃえばよくない?

ってことです。

 

編集するファイルはrhythmbox-3.0.2/shell/rb-play-order.hとrhythmbox-3.0.2/shell/rb-play-order-linear.cの2つです。

 

まずはrb-play-order.hで1曲ループを切り替えるためのフラグを宣言します。

ここは簡単で、

RBShellPlayer *      rb_play_order_get_player        (RBPlayOrder *porder);
RBSource *           rb_play_order_get_source        (RBPlayOrder *porder);
RhythmDB *           rb_play_order_get_db            (RBPlayOrder *porder);
RhythmDBQueryModel * rb_play_order_get_query_model   (RBPlayOrder *porder);
gboolean             rb_play_order_model_not_empty   (RBPlayOrder *porder);

gboolean             rb_play_order_player_is_playing (RBPlayOrder *porder);

gboolean loop1_flag;

 

関数宣言をしている箇所の後に青字部分を追加するだけです。

書き加えたら保存して閉じてOKです。

 

続いてrb-play-order-linear.c。

開いたらまずrb_linear_play_order_get_next関数とrb_linear_play_order_get_previous関数を探しましょう。この2つの関数は名前の通りそれぞれ次曲/前曲を取得する関数です。

static RhythmDBEntry *
rb_linear_play_order_get_next (RBPlayOrder *porder)
{
	RhythmDBQueryModel *model;
	RhythmDBEntry *entry;

	g_return_val_if_fail (porder != NULL, NULL);
	g_return_val_if_fail (RB_IS_LINEAR_PLAY_ORDER (porder), NULL);

	model = rb_play_order_get_query_model (porder);
	if (model == NULL)
		return NULL;

        entry = rb_play_order_get_playing_entry (porder);
	if (entry != NULL) {
		RhythmDBEntry *next;
		next = rhythmdb_query_model_get_next_from_entry (model, entry);
		rhythmdb_entry_unref (entry);
		return next;
	} else {
		GtkTreeIter iter;
		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
			return NULL;
		return rhythmdb_query_model_iter_to_entry (model, &iter);
	}
}

 

太字部分が実際に次曲の情報を取得している部分です。entryが現在の曲情報、nextが次曲の情報であるので1曲ループにするにはずばり、

 

next = entry;

 

とすれば良いですね!(すごく……雑です……)

これを先ほど宣言したフラグと合わせて書き換えると、

static RhythmDBEntry *
rb_linear_play_order_get_next (RBPlayOrder *porder)
{
	RhythmDBQueryModel *model;
	RhythmDBEntry *entry;

	g_return_val_if_fail (porder != NULL, NULL);
	g_return_val_if_fail (RB_IS_LINEAR_PLAY_ORDER (porder), NULL);

	model = rb_play_order_get_query_model (porder);
	if (model == NULL)
		return NULL;

        entry = rb_play_order_get_playing_entry (porder);
	if (entry != NULL) {
		RhythmDBEntry *next;
		if (loop1_flag == TRUE)
		{
			next = entry;
		}
		else
		{
			next = rhythmdb_query_model_get_next_from_entry (model, entry);
			rhythmdb_entry_unref (entry);
		}
		return next;
	} else {
		GtkTreeIter iter;
		if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (model), &iter))
			return NULL;
		return rhythmdb_query_model_iter_to_entry (model, &iter);
	}
}

 

フラグがTRUEなら1曲ループにする、という実装です。(Cではbooleanが扱えませんがgtk+ではgboolean型が定義されておりbooleanを扱うことが可能です)ということで同じような変更をrb_linear_play_order_get_previousにも行います。

static RhythmDBEntry *
rb_linear_play_order_get_previous (RBPlayOrder *porder)
{
	RhythmDBQueryModel *model;
	RhythmDBEntry *entry, *prev;

	g_return_val_if_fail (porder != NULL, NULL);
	g_return_val_if_fail (RB_IS_LINEAR_PLAY_ORDER (porder), NULL);

	model = rb_play_order_get_query_model (porder);
	if (model == NULL)
		return NULL;

        entry = rb_play_order_get_playing_entry (porder);
	if (entry == NULL)
		return NULL;

	if (loop1_flag == TRUE)
	{
		prev = entry;
	}
	else
	{
		prev = rhythmdb_query_model_get_previous_from_entry (model, entry);
		rhythmdb_entry_unref (entry);
	}

	return prev;
}

 

これで1曲ループ関数の実装は終了です。(まだフラグの値を操作していないのでこのままでは動かないことに注意!)

 \

次回はボタンとフラグを同期する操作へ入っていきます。