반응형

C#에서 Windows Media Player를 이용해 오디오 파일을 플레이 해 보자.

 

아래 링크를 참고해 Windows Media Player COM Component를 가져오고 빌드시 메세지가 발생하지 않도록 하자.

(Windows Media Player 컴포넌트를 폼에 배치할 필요는 없다)

2021.11.21 - [C#] - C# Windows Media Player Audio/Video Play #1

 

폼과 버튼을 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using WMPLib;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        private string time;
 
        WindowsMediaPlayer wmp;
 
        public Form1()
        {
            InitializeComponent();
            
            wmp = new WindowsMediaPlayer();
 
            Timer T = new Timer();
            T.Interval = 1000;
            T.Tick += new EventHandler(Form1_Timer);
            T.Start();
        }
 
        private void Form1_Timer(object sender, System.EventArgs e)
        {
            if (wmp.playState == WMPPlayState.wmppsPlaying)
            {
                //time = wmp.controls.currentPositionString + " / " + wmp.controls.currentItem.durationString;
                //time = wmp.controls.currentPosition.ToString() + " / " + wmp.controls.currentItem.duration.ToString();
                time = TimeSpan.FromSeconds((int)wmp.controls.currentPosition).ToString() + " / "
                    + TimeSpan.FromSeconds((int)wmp.controls.currentItem.duration);
 
                Graphics G = CreateGraphics();
                //G.DrawString(time, Font, System.Drawing.Brushes.Black, 20, 70); // 글자가 겹친다.
                TextRenderer.DrawText(G, time, Font, new Point(2070), ForeColor, BackColor);
                G.Dispose();
            }
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    wmp.URL = dlg.FileName;
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            if (wmp.playState == WMPPlayState.wmppsPlaying)
            {
                wmp.controls.stop();
            }
        }
    }
}
 

 

소스를 입력한다.

 

오디오/비디오 파일을 플레이 할 수 있다. (비디오 파일은 오디오만 출력된다)

실행 파일과 함께 Interop.WMPLib.dll 파일이 존재해야 한다.

 

Using the Windows Media Player Control in a .NET Framework Solution

 

반응형
Posted by J-sean
:
반응형

 

2021.11.21 - [C#] - C# Windows Media Player Audio/Video Play #2

 

C#에서 Windows Media Player를 이용해 오디오/비디오 파일을 플레이 해 보자.

 

Toolbox의 원하는 곳에서 우클릭 - Choose Items...

 

COM Components - Windows Media Player 선택.

 

폼, 버튼, Windows Media Player를 적당히 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using WMPLib;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    axWindowsMediaPlayer1.URL = dlg.FileName;
                    axWindowsMediaPlayer1.Ctlcontrols.stop();   // 자동 재생 방지.
                    // The managed-code wrapper for the Windows Media Player control exposes
                    // the Controls object as Ctlcontrols to avoid collision with the Controls
                    // property inherited from System.Windows.Forms.Control.
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
    }
}
 

 

소스를 입력한다.

 

 

이대로 빌드해도 문제는 없지만 위와 같은 메세지가 나온다.

 

References - WMPLib - Properties - Embed Interop Types - False 선택

다시 빌드하면 아무 메세지도 나오지 않는다.

 

MP3등 오디오 파일 재생.

 

AVI, MP4등 비디오 파일 재생.

 

 

이번엔 실행하면 아무것도 보이지 않다가 오디오/비디오 파일을 선택하면 UI없이 플레이 하는 프로그램을 만들어 보자.

 

폼, 버튼, Windows Media Player를 배치한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
using WMPLib;
 
namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
 
            axWindowsMediaPlayer1.Visible = false;
            axWindowsMediaPlayer1.uiMode = "none";
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDialog dlg = new OpenFileDialog();
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    axWindowsMediaPlayer1.URL = dlg.FileName;
                    axWindowsMediaPlayer1.Visible = true;
                }
            } catch (Exception exc)
            {
                MessageBox.Show(exc.Message);
            }
        }
 
        private void button2_Click(object sender, EventArgs e)
        {
            if (axWindowsMediaPlayer1.playState == WMPPlayState.wmppsPlaying)
            {
                axWindowsMediaPlayer1.Ctlcontrols.stop();
                // The managed-code wrapper for the Windows Media Player control exposes
                // the Controls object as Ctlcontrols to avoid collision with the Controls
                // property inherited from System.Windows.Forms.Control.
                
                axWindowsMediaPlayer1.Visible = false;
            }            
        }
    }
}
 

 

소스를 입력하고 빌드한다.

 

WMP가 보이지 않는다. Play 버튼을 클릭하고 비디오 파일을 선택한다.

 

비디오가 UI없이 플레이된다.

 

실행 파일과 함께 Interop.WMPLib.dll 파일이 존재해야 한다.

 

Using the Windows Media Player Control in a .NET Framework Solution

 

반응형
Posted by J-sean
:
반응형

레트로파이에 한글 폰트, 게임 마키, 이미지, 플레이 영상, 설명등을 넣어 보자.

 

2020/02/13 - [Raspberry Pi & Arduino] - Raspberry Pi Desktop(Debian), Ubuntu에서 RetroPie 설치하기

 

특별한 설정을 하지 않았다면 레트로파이(아케이드)에 게임 이름 정도만 표시된다. 등록된 게임을 잘 아는 사람은 문제 없겠지만 모르는 사람은 무슨 게임인지 알 수가 없다. 처음 하는 사람도 어떤 게임인지 알 수 있도록 이미지, 플레이 영상, 설명등을 넣어 보자.

 

Cabin-Bold.ttf 가 기본(영문) 폰트다. 한글이 표시 될 수 있도록 원하는 한글 폰트(KATURI.TTF)를 /etc/emulationstation/themes/carbon/art/ 에 복사한다. 

 

/etc/emulationstation/themes/carbon/ 에 있는 'carbon.xml', 'theme.xml' 파일에 설정된 폰트를 변경한다.

 

두 파일을 열고 'Cabin-Bold.ttf'가 나오는 부분을 모두 한글 폰트 이름(KATURI.TTF)으로 바꾼다. (원래 있던 'Cabin-Bold.ttf' 파일을 지우고 한글 폰트 이름을 'Cabin-Bold.ttf'로 바꾸면 두 파일의 내용을 바꾸지 않아도 된다)

 

 

RetroPie를 실행해 보면 바뀐 폰트가 적용되어 있다.

 

/opt/retropie/configs/all/emulationstation/gamelists/arcade/gamelist.xml 에 게임 이름, 이미지, 플레이 영상, 설명등을 등록 할 수 있다.

 

gamelist.xml
5.73MB

 

아래와 같은 형식으로 작성 한다.

 

<?xml version="1.0"?>

<gameList>

<game>

<path>게임 파일 경로</path>

<name>게임 이름</name>

<image>게임 이미지 파일 경로</image>

<video>게임 플레이 영상 파일 경로</video>

<marquee>게임 마키 파일 경로</marquee>

<developer>게임 제작사</developer>

<publisher>게임 판매사</publisher>

<genre>게임 장르</genre>

<players>게임 플레이어 수</players>

<releasedate>게임 발매일</releasedate>

<desc>게임 설명</desc>

</game>

<game>

...

</game>

...

</gameList>

 

'gamelist.xml'에 등록한 파일 경로 및 이름대로 marquee, snap, video 디렉토리를 /home/pi/RetroPie/roms/arcade/ 에 생성하고 각 디렉토리에 맞는 파일을 복사한다.

 

 

마키(marquee)

 

이미지(image)/스냅(snap)

 

영상(video)

 

 

예를 들어 marquee 디렉토리의 내용은 위와 같다.

 

RetroPie를 실행해 보자. ARCADE - 메탈 슬러그의 마키, 플레이 영상, 게임 설명등이 디스플레이 된다.

 

스트리트 파이터 2의 내용도 잘 디스플레이 된다.

 

반응형
Posted by J-sean
:
반응형

리눅스(우분투) 서버 같은 콘솔 환경에서도 비디오 플레이어를 사용할 수 있다.


mpv를 설치한다.


--vo=drm 옵션, 영상 파일 이름과 함께 실행한다.


자막 파일이 있다면 자막도 표시된다. 주요 단축키 목록은 아래와 같다.


  • LEFT and RIGHT: Seek backward/forward 5 seconds. Shift+arrow does a 1 second exact seek

  • UP and DOWN: Seek forward/backward 1 minute. Shift+arrow does a 5 second exact seek

  • p / SPACE: Pause (pressing again unpauses).

  • q: Stop playing and quit.

  • Q: Like q, but store the current playback position. Playing the same file later will resume at the old playback position if possible.

  • 9 and 0: Decrease/increase volume.

  • m: Mute sound.

  • o (also P): Show progression bar, elapsed time and total duration on the OSD.

  • O: Toggle OSD states between normal and playback time/duration.

  • v: Toggle subtitle visibility.

  • z and Z: Adjust subtitle delay by +/- 0.1 seconds. The x key does the same as Z currently, but use is discouraged.

  • r and R: Move subtitles up/down. The t key does the same as R currently, but use is discouraged.

  • s: Take a screenshot.

  • S: Take a screenshot, without subtitles. (Whether this works depends on VO driver support.)

  • Shift+PGUP and Shift+PGDWN: Seek backward or forward by 10 minutes. (This used to be mapped to PGUP/PGDWN without Shift.)

  • 1 and 2: Adjust contrast.

  • 3 and 4: Adjust brightness.

  • 5 and 6: Adjust gamma.

  • 7 and 8: Adjust saturation.


반응형
Posted by J-sean
:
반응형

RetroPie installed on a PC can be too fast to play retro games. You can adjust(slow down) its speed by changing video_frame_delay value.


라즈베리 파이가 아닌 PC에 레트로파이를 설치한 경우 성능 차이로 인해 레트로 게임들이 너무 빨라 진행 할 수 가 없다. video frame delay 설정을 변경해 속도를 조절해 보자.


RetroPie Configuration을 선택 한다.


Configuration Editor를 선택 한다.


Advanced Configuration을 선택 한다.


Configure Libretro options를 선택 한다.



all/retroarch.cfg를 선택 한다.


video_frame_delay를 선택 한다.


Edit를 선택 한다.


15 이하의 적당한 숫자를 입력 하고 OK를 선택 한다. 다시 게임을 진행해 보면 속도가 적당히 변경되어 있다.



Configure Libretro options가 아닌 Manually edit RetroArch configurations에서도 변경 가능 하다.


all/retroarch.cfg를 선택 한다.


원래는 video_frame_delay가 주석처리(#)되어 있는데 위와 같이 주석을 삭제하고 적당한 값으로 바꾸면 된다.


특정 게임에서 잠시 video frame delay 값을 변경하고 싶다면 Hotkey(Select) + X 를 누른다.



Quick Menu가 표시 된다. 라즈베리파이(라즈비안)가 한국어로 설정되어 있다면 Quick Menu의 글자가 제대로 표시되지 않는다. 언어 설정을 영어로 바꾸면 제대로 표시된다.


Latency를 선택 한다.


Frame Delay를 선택 한다.


원하는 값을 선택 하고 게임으로 돌아가면 변경된 값이 적용 된다. 이 방법은 일회성이며 게임을 다시 시작하면 원래 값으로 돌아 간다. 이 상태를 저장하고 싶다면 Quick Menu에서 Save State를 선택 한다.


반응형
Posted by J-sean
:
반응형

간단한 웹서버용 HTML 문서 작성 예제


2019/10/08 - [Linux] - Build your own web server with Fedora linux - 페도라 리눅스로 간단한 웹서버 만들기


아래 내용으로 index.html 파일을 작성 하고 /var/www/html에 저장 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!doctype html>
<html lang="ko">
    <head>
        <meta charset="utf-8">
        <title>J.Sean's simple web server</title>
        <style>
            a{
                text-decoration:none;
                color:black;
            }
 
        </style>
    </head>
 
    <body>
        <h1>
        <br>--- J.sean's simple web server ---
        <br>OS: Fedora
        <br>HTTP Server: Apache
        <br>
        <a href="https://s-engineer.tistory.com/" target="_blank">Click me to visit J.Sean's blog</a><br><br>
 
        Alien 3<br>
        <video src="./data/Alien.mp4" width="960" height="520" autoplay controls>
        <track label="Korean" kind="subtitles" srclang="ko" src="./data/Alien.vtt" default></video><br><br>
        
        <a href="https://s-engineer.tistory.com/" target="_blank">
        <img src="./download/animal.jpg">
        </a>
 
        <br>
        <a href="./download/file.zip" download>File (file.zip)</a><br>
 
        </h1>
    </body>
</html>



./data, ./download 디렉토리를 만들고 index.html 내용에 필요한 데이터를 저장 한다.


서버에 접속하면 비디오 플레이어, 웹링크, 파일링크, 사진등이 표시된 웹 페이지가 열린다.


반응형
Posted by J-sean
:
반응형

A YouTubePlayer provides methods for loading, playing and controlling YouTube video playback.


Copy 'YouTubeAndroidPlayerApi.jar' to 'app/libs' and sync project with gradle files.


<AndroidManifest.xml>

1
    <uses-permission android:name="android.permission.INTERNET"/>



<activity_main.xml>

1
2
3
4
    <com.google.android.youtube.player.YouTubePlayerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/youTubePlayerView"/>



<MainActivity.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
public class MainActivity extends YouTubeBaseActivity {
 
    YouTubePlayerView youTubePlayerView;
    YouTubePlayer player;
 
    private static String API_KEY = "AIyaSyDpsLddBj2ISc-NHU4sxWFh4JlcHNELir8";  // Your API Key
    private static String videoId = "Mx5GmonOiKo"// Youtube video ID from https://youtu.be/Mx5GmonOiKo
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        initPlayer();
 
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadVideo();
            }
        });
 
        Button button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                playVideo();
            }
        });
    }
 
    public void initPlayer() {
        youTubePlayerView = findViewById(R.id.youTubePlayerView);
        youTubePlayerView.initialize(API_KEY, new YouTubePlayer.OnInitializedListener() {
            @Override
            public void onInitializationSuccess(YouTubePlayer.Provider provider, final YouTubePlayer youTubePlayer, boolean b) {
 
                player = youTubePlayer;
 
                youTubePlayer.setPlayerStateChangeListener(new YouTubePlayer.PlayerStateChangeListener() {
                    @Override
                    public void onLoading() {
 
                    }
 
                    @Override
                    public void onLoaded(String s) {
                        Toast.makeText(getApplicationContext(), s + " loaded", Toast.LENGTH_SHORT).show();
                    }
 
                    @Override
                    public void onAdStarted() {
 
                    }
 
                    @Override
                    public void onVideoStarted() {
 
                    }
 
                    @Override
                    public void onVideoEnded() {
 
                    }
 
                    @Override
                    public void onError(YouTubePlayer.ErrorReason errorReason) {
 
                    }
                });
            }
 
            @Override
            public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
 
            }
        });
    }
 
    public void loadVideo() {
        if (player != null) {
            player.cueVideo(videoId);
            // Loads the specified video's thumbnail and prepares the player to play the video, but does not download any of the video stream
            // until play() is called.
        }
    }
 
    public void playVideo() {
        if (player != null) {
            if (player.isPlaying()) {
                player.pause();
            } else {
                player.play();
            }
        }
    }
}


Your activity needs to extend YouTubeBaseActivity.



Run the app and click the LOAD button.


It loads the video.


Play and enjoy the video.


반응형
Posted by J-sean
:
반응형

You can stream a video file with VideoView.


<AndroidManifest.xml>

1
    <uses-permission android:name="android.permission.INTERNET"/>



<MainActivity.java>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class MainActivity extends AppCompatActivity {
 
    VideoView videoView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        videoView = findViewById(R.id.videoView);
 
        MediaController mediaController = new MediaController(this);
        videoView.setMediaController(mediaController);
 
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                videoView.setVideoURI(Uri.parse("http://nexoft.tk/data/WhileYouWereSleeping.mp4")); // or your video file url.
                videoView.requestFocus();
                videoView.start();
            }
        });
 
        videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                Toast.makeText(getApplicationContext(), "Video play completed", Toast.LENGTH_SHORT).show();
            }
        });
 
        videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                String message;
 
                switch (what) {
                    case MediaPlayer.MEDIA_ERROR_UNKNOWN:
                        message = "MEDIA_ERROR_UNKNOWN";
                        break;
 
                    case MediaPlayer.MEDIA_ERROR_SERVER_DIED:
                        message = "MEDIA_ERROR_SERVER_DIED";
                        break;
 
                    default:
                        message = "No what";
                }
 
                switch (extra) {
                    case MediaPlayer.MEDIA_ERROR_IO:
                        message += ", MEDIA_ERROR_IO";
                        break;
 
                    case MediaPlayer.MEDIA_ERROR_MALFORMED:
                        message += ", MEDIA_ERROR_MALFORMED";
                        break;
 
                    case MediaPlayer.MEDIA_ERROR_UNSUPPORTED:
                        message += ", MEDIA_ERROR_UNSUPPORTED";
                        break;
 
                    case MediaPlayer.MEDIA_ERROR_TIMED_OUT:
                        message += ", MEDIA_ERROR_TIMED_OUT";
                        break;
 
                    default:
                        message += ", No extra";
                }
                Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
 
                //    Returns true if the method handled the error, false if it didn't. Returning false, or not having an OnErrorListener
                //    at all, will cause the OnCompletionListener to be called.
                return true;
            }
        });
    }
}




Run the app and click the PLAY button.


It may not be able to stream the video and show an error message in AVD.


It can stream the video in the actual device.


반응형
Posted by J-sean
: