パピーでプログラミングしてみる(初級編)

パピーを名犬にするための技、テクニック

モデレータ: 暇人, YoN, nyu

新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

Re: シェルから gtkdialog3 を使う

投稿記事 by 新谷 »

シノバーさん、愚にもつかないコードに丁寧にコメント下さって有難うございます :D :D
シノバー さんが書きました:IFSはシェル変数で、区切り符号ですね。それを変更してるのか、デフォルトにしてるのか?その上で gtkdialog3の標準出力を一行ずつ eval で評価してますね。

ここは for を使わず、単純に次の1行でOKです。

コード: 全て選択

eval  $(gtkdialog3 --program=MAIN_DIALOG --center )
上記コードは gtkdialog3の出力が 「変数=値」の羅列であることを前提にしています。
そうでない出力が出るような使い方では、もう少していねいにフィルタを掛けると良いかもしれません。たとえば

コード: 全て選択

eval  $(gtkdialog3 --program=MAIN_DIALOG --center| grep '^EXIT=' )
gtkdialog3の出力を使わない場合(どのボタンが押されたか知る必要がない場合)はもっと単純に

コード: 全て選択

gtkdialog3 --program=MAIN_DIALOG --center >/dev/null
な、る、ほ、ど、です。
IFSとeval コマンドの使い方がイマイチ分からなかったのですが、シノバーさんの解説で少しは実感が湧いてきました :o :o

参考:僕の持ってるシェルスクリプトのリファレンス本から
・eval
一般に、シェルは入力されたコマンドやその引数に対して、パラメータ展開やコマンド置換などの各種解釈を行った上で実際にコマンドを実行します。eval コマンドは、evalコマンドに渡された引数に対して、再度パラメータ展開やコマンド置換などの解釈を行い、その結果のコマンドを実行します。シェルがeval コマンドを実行する時点では、引数は一度解釈されているため、evalコマンドを使うと、結果的に引数の解釈が二回行われることになります。
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

Re: ネットラジオを聴くアプリ (もっと単純版)

投稿記事 by 新谷 »

シノバー さんが書きました:停止ボタンを押さずに右上「×」でウィンドウを閉じるとシェルスクリプトに戻ってくるので、そこで killall madplay を実行してやれば演奏が停止します。ウィンドウを閉じると無条件に停止させるので、ボタンの状態を見る必要はないですね。
言われてみればコロンブス卵です :o :o 何で気がつかなかったんだろう....盲点でした。
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

ネットラジオを聴くアプリ (C版・プロトタイプ)

投稿記事 by 新谷 »

じゃあ....頑張って....Cで書いてみようと....思います :x :x

madplay-radio001.c

コード: 全て選択

#include <gtk/gtk.h>
#include <stdlib.h>

static void      /* ボタンを押したときの挙動 */
cb_button (GtkWidget *widget, gpointer user_data)
{
  g_print ("%s\n", (gchar *) user_data);
  system ("wget -q -O - http://anime.com.pl:8000/radioLQ.mp3 | madplay - &"); 
}

static void    /* ウィンドウの「x」ボタンを押したときの挙動 */
destroy_data (gpointer user_data, GClosure *closure)
{
  g_free ((gchar *) user_data);
  system ("killall madplay");
}

int main (int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *button;
  gulong    handle;
  
  gtk_init (&argc, &argv);

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "ラジオ001");
  gtk_widget_set_size_request (window, 170, 30);
  g_signal_connect (G_OBJECT (window), "destroy", 
		    G_CALLBACK (gtk_main_quit), NULL);
  
  button = gtk_button_new_with_label ("ネットラジオを聴く");
  gtk_container_add (GTK_CONTAINER (window), button);

  g_signal_connect_data (G_OBJECT (button), "clicked",  /* クリックした時のシグナル.....こんなんでいい? */
			 G_CALLBACK (cb_button),
			 g_strdup ("http://anime.com.pl:8000/radioLQ.mp3 から受信しています....."), destroy_data, 0);  /* コマンドラインでのメッセージ */
  gtk_widget_show_all (window);

  gtk_main ();

  return 0;
}

もう自分でも何が何だか..... :cry: :cry: 多分ツッコミ処満載です。
でもいいんだ!! はじめはみんなこんな感じからスタートしたんじゃなかろうか :twisted:

あと、GTKで書くと英単語が長くなって綴りミスが多くなるなぁと思いました。慣れでしょうか.....。Valaで書くとどうなるだろう??
コンパイルは以下のようにして下さい。

コード: 全て選択

 gcc -o madplay-radio001 madplay-radio001.c `pkg-config --cflags --libs gtk+-2.0`
実行すると↓のようになります。
画像
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

C言語 sprintf()関数について

投稿記事 by 新谷 »

文字列を編集するのに便利な関数なんだろうなぁ、と。
参考リンク: http://www9.plala.or.jp/sgwr-t/lib/sprintf.html

参考リンクにある参考コード

コード: 全て選択

#include        <stdio.h>

int     main(void)
{
        int             i;
        char    str[100];
        char    str1[] = "文字列";
        char    str2[] = "連結";
        char    str3[] = "お手軽";

        for (i=1; i<=10; i++) {
                /* ループ回数を文字列に格納 */
                sprintf(str,"ループ回数:%2d",i);
                puts(str);
        }

        sprintf(str,"%sの%sだって%sよ",str1,str2,str3);
        puts(str);

        return 0;
}
system()関数(Linuxコマンドがそのまま使える関数)とも相性がよさげ。
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

ネットラジオを聴くアプリ (C版・CUI その1)

投稿記事 by 新谷 »

で、ネットラジオを聴くアプリのコア部分をC言語で書いてみようと思ったのです。
コアと言っても

コード: 全て選択

# wget -q -O - ラジオのURL | madplay - 
だけなんですが。

madplay-radio002.c

コード: 全て選択

#include        <stdio.h>
#include	<stdlib.h>  /* system(),sprintf()関数のため */
#include	<string.h> /* strcpy()関数のため */

int     main(int argc, char *argv[])
{
	char    command[120];
	char	 url[90];
	char    str1[] = "wget -q -O - ";
//	char    str2[] = ""; /* 拡張のため 現時点では意味無し*/
	char    str3[] = "|";
	char str4[] = "madplay -";

	if (argc != 0) { strcpy(url,argv[1]); }
	else {printf("URLを引数にして実行して下さい。"); exit(0); }

		sprintf(command,"%s%s%s%s",str1,url,str3,str4);

		printf("%s から受信します....。\n\n",url);
		printf("実行コマンド: %s \n\n",command);
		/* 実行コマンド: wget -q -O - URL | madplay -  */ 
		
		system(command);

        return 0;
}
コンパイル

コード: 全て選択

gcc -o madplay-radio002 madplay-radio002.c
実行

コード: 全て選択

# ./madplay-radio002 http://anime.com.pl:8000/radioLQ.mp3 &
とか....URLはお好みで。

ところで、引数なしで実行すると.....

コード: 全て選択

# ./madplay-radio002 
Segmentation fault
になってしまいます。
「URLを引数にして実行して下さい。」のメッセージがでて欲しいのに..... :x :x
詳しい方、もしお時間あればご教授いただきたいです。
Endeavor_wako
記事: 380
登録日時: 09/09/18(金) 01:54

Re: パピーでプログラミングしてみる(初級編)

投稿記事 by Endeavor_wako »

ネタにマジレスかも知れませんが、敢えて。
命令だけなら argc は 1 になりませんか?
Main:NEC VersaPro VB-B (Core i5, RAM4GB, SSD, LinuxMint (xfce4,amd64))
Sub:Fujitsu note pc (Celeron、RAM8GB, SSD, LinuxMint (xfce4, amd64))

Puppyを使わなくなって久しい今日この頃。Raspiや32ビットPCにdebian入れてヘッドレスで
遊んでます。
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

Re: パピーでプログラミングしてみる(初級編)

投稿記事 by 新谷 »

申し訳ないですが、ネタじゃないんです....orz
某首相流に言い訳すると、「ネタだとおっしゃられるかもしれませんが、知らなかったということが、あり得てるんです!!!」

解決しました。

コード: 全て選択

   if (argc == 1) {printf("URLを引数にして実行して下さい。\n"); exit(0); }
   else { strcpy(url,argv[1]); }
Endeavor_wakoさん、本当に有り難うございます<(_ _)>
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

シェルスクリプトでハローワールド (GUI編)

投稿記事 by 新谷 »

おさらいも兼ねて。シェルスクリプトでGTKを使って書くとこんなかんじ。

hello-shell-gui.sh

コード: 全て選択

#!/bin/sh

export MAIN_DIALOG='
<window title="hello">
<vbox>
<hbox>

    <button><label>Hello World!</label></button>

</hbox>
</vbox>
</window>
'
gtkdialog3 --program=MAIN_DIALOG
なんかホッとする。

実行属性を付ける

コード: 全て選択

#chmod +x ./hello-shell-gui.sh
実行

コード: 全て選択

./hello-shell-gui.sh
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

Genie(Vala)でハローワールド (GUI編)

投稿記事 by 新谷 »

こんな感じになりました。シンプルといえばシンプル。

hello-genie-gui.gs

コード: 全て選択

uses 
	Gtk

init
	Gtk.init (ref args)
	var test = new MADO ()
	test.show_all ()
	Gtk.main ();

class MADO : Window
	init
		title = "hello"
		default_height = 100
		default_width = 200

		destroy += Gtk.main_quit  /* ウィンドウの「x」ボタンがクリックされたときの挙動 */

		var button = new Button.with_label ("Hello World!")
		button.clicked += Gtk.main_quit /* ボタンがクリックされたときの挙動 */
		add (button)
コンパイル

コード: 全て選択

#valac --pkg gtk+-2.0 hello-genie-gui.gs
実行

コード: 全て選択

#./hello-genie-gui
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

C言語(GTK)でハローワールド (GUI編)

投稿記事 by 新谷 »

で、問題のC。

書いていく順番は以下のようになりました。小規模なアプリならこんな感じでいけそう。
1. ボタンがクリックされたときに呼び出される関数
2. ウィンドウの「x」ボタンがクリックされたときに呼び出される関数

3. ウィンドウの表示設定
4. ウィンドウの「x」ボタンがクリックされたときに呼び出される関数の設定

5. ウィンドウの中のボタンの表示設定
6. ボタンがクリックされたときに呼び出される関数の設定

7. 設定後の表示とメインループ

hello-gtk-gui.c

コード: 全て選択

#include <gtk/gtk.h>

static void   /* ボタンがクリックされたときに呼び出される関数 */
cb_button_clicked (GtkWidget *button, gpointer user_data)
{  gtk_main_quit (); }
		   
static void    /* ウィンドウの「x」ボタンがクリックされたときに呼び出される関数 */
destroy_data (gpointer user_data, GClosure *closure)
{  gtk_main_quit (); }

int main (int argc, char **argv)
{
  gtk_init (&argc, &argv);

  /* ウィンドウの表示設定 */
  GtkWidget *MADO;
  MADO = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request (MADO, 200, 100);  

  /* ウィンドウの「x」ボタンがクリックされたときに呼び出される関数の設定 */ 
   g_signal_connect (G_OBJECT (MADO), "destroy",
		G_CALLBACK (gtk_main_quit), NULL);

	{
	/* ウィンドウの中のボタンの表示設定 */
	GtkWidget *BOTAN;    
	BOTAN = gtk_button_new_with_label ("Hello World!");
	gtk_container_add (GTK_CONTAINER (MADO), BOTAN);

		/* ボタンがクリックされたときに呼び出される関数の設定 */      
		g_signal_connect (G_OBJECT (BOTAN), "clicked",
			G_CALLBACK (cb_button_clicked), NULL);
  	}

  /* 設定後の表示とメインループ */
  gtk_widget_show_all (MADO);
  gtk_main ();

  return 0;
}

コンパイル

コード: 全て選択

#gcc -o hello-gtk-gui hello-gtk-gui.c `pkg-config --cflags --libs gtk+-2.0`
実行

コード: 全て選択

#./hello-gtk-gui.c
画像
アバター
みのむし
記事: 1164
登録日時: 08/09/10(水) 13:56
お住まい: 福岡市中央区草香江1-2-40-101号
連絡する:

Re: パピーでプログラミングしてみる(初級編)

投稿記事 by みのむし »

新谷さん
 興味深く読ませていただきました。
Genie で「madplay-radio001」をプログラミングしてみては :?:
URLを渡すのはどのようにプログラミングするんでしょうか :?:

ネットラジオ構想

・URLオプションは指定しないで起動
・起動したら、チャンネル(URL)選択画面が出るので、そこでチャンネル選択
・チャンネルは初めから設定してあるものもあるが、
・ユーザーが追加登録出来るようになっている。
・後は、ボリュームを付ける事
みのむし
Notebook PC HP G62
CPU: Intel(R) Core(TM)i5 M450 @ 2.40GHz
MEM: 4GB
Puppy Linux Quickset 5.1.1 JP
PC内蔵無線LANデバイス RTL8171(r8192se_pci)
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

Re: パピーで....

投稿記事 by 新谷 »

みのむしさん、どうもです。
Genie で「madplay-radio001」をプログラミングしてみては :?:
端的に言ってまだまだ勉強不足ですね.....集中して勉強すれば2週間くらいでできそうな気もしますが。

ところで、ドキュメント/テキストリーダーの進捗具合はいかかですか?
アバター
みのむし
記事: 1164
登録日時: 08/09/10(水) 13:56
お住まい: 福岡市中央区草香江1-2-40-101号
連絡する:

Re: パピーでプログラミングしてみる(初級編)

投稿記事 by みのむし »

>端的に言ってまだまだ勉強不足ですね.....集中して勉強すれば2週間くらいでできそうな気もしますが。

面倒な事を言ってすみません。でも期待しています。
私も時間があれば...プログラミングしたい所ですが...
新谷さんの手で完成するのがふさわしいかと...

>ところで、ドキュメント/テキストリーダーの進捗具合はいかかですか?

ストップ状態です。
最後に編集したユーザー みのむし [ 10/02/26(金) 22:21 ], 累計 1 回
みのむし
Notebook PC HP G62
CPU: Intel(R) Core(TM)i5 M450 @ 2.40GHz
MEM: 4GB
Puppy Linux Quickset 5.1.1 JP
PC内蔵無線LANデバイス RTL8171(r8192se_pci)
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

grep の巻 (C言語・簡易)

投稿記事 by 新谷 »

grepコマンドってUTF-8環境だと遅いので、簡易grepをC言語で書いてみたいなぁと思っていたのですが、そのものズバリをウェブ上でみつけてしまいました。 http://oshiete1.goo.ne.jp/qa5581054.html

コード: 全て選択

/* A simple grep by Mac OSX
* file name: gunofkid.c
* compile: gcc gunofkid.c
* execution: ./a.out 'key word' <file1 <file2 <file...>>>
*/

#include <stdio.h>
#include <string.h> // strstr()
#include <stdlib.h> // exit()

#define SIZE 256

int main(int argc, char *argv[]) {
int line;
char *file_name, *key_word, *temp, read_buff[SIZE];
FILE *fp;

if (argc<3) {
printf("Parameter error.\n");
return 0;
}

while (argc-- > 2) {
/* 任意ファイルを開く */
file_name = argv[argc];
fp = fopen(file_name, "r");
if (fp == NULL) {
printf("%s file not found.\n", file_name);
exit(1);
}

/* メイン・プログラム部 */
key_word = argv[1];
line = 0;
fgets(read_buff, SIZE, fp);
while (!feof(fp)) {
line += 1;
if (strstr(read_buff, key_word) != NULL)
printf("%s %d: %s", file_name, line, read_buff);
fgets(read_buff, SIZE, fp);
}

/* 任意ファイルを閉じる */
fclose(fp);
}

return 0;
}

hiroshi09sさんに感謝<(_ _)>
hiroshi09sさんによると、
なお、引数の取り方やファイルの読み込み方は定番中の定番ですから覚えておいてください。また、 while{} 中の if{} 文節内を改良すれば、様々なパターン検索に拡張できますので、是非トライしてみてください。
とのことですので、俺も精進しよう。

whileの条件の書き方はまだよく分かってないなぁ.....まーだいたい想像でOKということに。
キモの部分は

コード: 全て選択

if (strstr(read_buff, key_word) != NULL)
ですね。
新谷
記事: 934
登録日時: 08/10/09(木) 18:52
お住まい: 大阪

C言語 strstr()関数について

投稿記事 by 新谷 »

・書式
strstr(A,B);

・機能
文字列AにBが含まれているかどうか調べる。
含まれていればそれ以降の文字列を返す。

大文字と小文字は区別される。
大文字と小文字は区別したくない場合はstristr() 関数を使う。
返信する