mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Media: Update.
git-svn-id: svn://ultimatepp.org/upp/trunk@3786 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
8a16fa8788
commit
185e716cb7
11 changed files with 524 additions and 419 deletions
|
|
@ -1,15 +0,0 @@
|
|||
uses
|
||||
CtrlLib,
|
||||
Controls4U,
|
||||
GridCtrl,
|
||||
Media,
|
||||
SliderCtrlX;
|
||||
|
||||
file
|
||||
main.cpp,
|
||||
demo.lay,
|
||||
srcdoc.tpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI MT";
|
||||
|
||||
19
bazaar/MediaPlayer/Media_demo.upp
Normal file
19
bazaar/MediaPlayer/Media_demo.upp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
description "Media package examples\377";
|
||||
|
||||
uses
|
||||
CtrlLib,
|
||||
Controls4U,
|
||||
Media;
|
||||
|
||||
file
|
||||
main.cpp,
|
||||
demo.lay,
|
||||
demoMediaPlayer.cpp,
|
||||
demoMediaPlayer.lay,
|
||||
demoVolumeCtrl.cpp,
|
||||
demoVolumeCtrl.lay,
|
||||
srcdoc.tpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI MT";
|
||||
|
||||
|
|
@ -1,32 +1,6 @@
|
|||
LAYOUT(Main, 320, 300)
|
||||
ITEM(Label, secondsLabel, SetFrame(FieldFrame()).RightPosZ(148, 56).BottomPosZ(49, 19))
|
||||
ITEM(Button, butPause, SetLabel(t_("Pause")).RightPosZ(52, 40).BottomPosZ(48, 20))
|
||||
ITEM(Button, butFormat, SetLabel(t_("Format")).RightPosZ(8, 40).BottomPosZ(24, 20))
|
||||
ITEM(Button, butPlay, SetLabel(t_("Play")).RightPosZ(96, 48).BottomPosZ(48, 20))
|
||||
ITEM(EditFile, file, HSizePosZ(4, 208).BottomPosZ(49, 19))
|
||||
ITEM(Option, blackWhite, SetLabel(t_("Grayscale effect")).LeftPosZ(188, 100).BottomPosZ(5, 19))
|
||||
ITEM(Option, motionDetect, SetLabel(t_("Motion detect")).LeftPosZ(96, 88).BottomPosZ(5, 19))
|
||||
ITEM(Option, showLogo, SetLabel(t_("Show logo")).LeftPosZ(188, 72).BottomPosZ(25, 19))
|
||||
ITEM(Option, rgb, SetLabel(t_("RGB/YUV")).LeftPosZ(96, 68).BottomPosZ(25, 19))
|
||||
ITEM(Option, fullScreen, SetLabel(t_("Full screen")).LeftPosZ(4, 88).BottomPosZ(5, 19))
|
||||
ITEM(Option, forceAspect, SetLabel(t_("Force aspect")).LeftPosZ(4, 88).BottomPosZ(25, 19))
|
||||
ITEM(EditString, seconds, RightPosZ(148, 56).BottomPosZ(49, 19))
|
||||
ITEM(SliderCtrlX, slider, HSizePosZ(4, 8).BottomPosZ(64, 40))
|
||||
ITEM(Button, butStop, SetLabel(t_("Stop")).RightPosZ(8, 40).BottomPosZ(48, 20))
|
||||
ITEM(MediaPlayer, player, SetFrame(InsetFrame()).HSizePosZ(4, 4).VSizePosZ(4, 104))
|
||||
END_LAYOUT
|
||||
|
||||
LAYOUT(Format, 400, 392)
|
||||
ITEM(ArrayCtrl, arrAudio, HSizePosZ(4, 4).TopPosZ(200, 100))
|
||||
ITEM(Label, dv___1, SetLabel(t_("Audio streams")).LeftPosZ(4, 104).TopPosZ(180, 19))
|
||||
ITEM(ArrayCtrl, arrVideo, HSizePosZ(4, 4).TopPosZ(68, 100))
|
||||
ITEM(Label, dv___3, SetLabel(t_("Video streams")).LeftPosZ(4, 104).TopPosZ(48, 19))
|
||||
ITEM(Label, fileName, SetFrame(ThinInsetFrame()).HSizePosZ(64, 4).TopPosZ(4, 19))
|
||||
ITEM(Label, dv___5, SetLabel(t_("File name:")).LeftPosZ(4, 60).TopPosZ(4, 19))
|
||||
ITEM(Label, duration, SetFrame(ThinInsetFrame()).LeftPosZ(64, 60).TopPosZ(24, 19))
|
||||
ITEM(Label, dv___7, SetLabel(t_("Duration:")).LeftPosZ(4, 60).TopPosZ(24, 19))
|
||||
ITEM(Button, ok, SetLabel(t_("Close")).RightPosZ(4, 64).BottomPosZ(4, 20))
|
||||
ITEM(DocEdit, tags, SetFrame(ThinInsetFrame()).WantFocus(false).SetEditable(false).HSizePosZ(4, 84).VSizePosZ(324, 4))
|
||||
ITEM(Label, dv___10, SetLabel(t_("Tags")).LeftPosZ(4, 30).TopPosZ(304, 19))
|
||||
LAYOUT(Main, 400, 164)
|
||||
ITEM(ArrayCtrl, grid, HSizePosZ(4, 4).VSizePosZ(32, 4))
|
||||
ITEM(Label, dv___1, SetLabel(t_("Choose a Media demo")).LeftPosZ(8, 128).TopPosZ(8, 19))
|
||||
ITEM(Button, butRun, SetLabel(t_("Run")).RightPosZ(4, 76).TopPosZ(4, 24))
|
||||
END_LAYOUT
|
||||
|
||||
|
|
|
|||
393
bazaar/MediaPlayer/demoMediaPlayer.cpp
Normal file
393
bazaar/MediaPlayer/demoMediaPlayer.cpp
Normal file
|
|
@ -0,0 +1,393 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#include <Media/MediaPlayer.h>
|
||||
#include <Controls4U/Controls4U.h>
|
||||
#include <Media/VolumeCtrl.h>
|
||||
|
||||
#define LAYOUTFILE <Media_demo/demoMediaPlayer.lay>
|
||||
#include <CtrlCore/lay.h>
|
||||
|
||||
struct MediaPlayerDemo : public WithMainMediaPlayer<TopWindow> {
|
||||
typedef MediaPlayerDemo CLASSNAME;
|
||||
void Play() {
|
||||
butPlay.Disable();
|
||||
butPause.Enable();
|
||||
butStop.Enable();
|
||||
butFormat.Disable();
|
||||
file.Disable();
|
||||
seconds.Hide();
|
||||
secondsLabel.SetText("0");
|
||||
sliderPosition.SetData(0);
|
||||
|
||||
if (!player.Play())
|
||||
Exclamation(player.GetError());
|
||||
|
||||
seconds.SetText("0");
|
||||
sliderPosition.SetData(0);
|
||||
butPlay.Enable();
|
||||
butPause.Disable();
|
||||
butStop.Disable();
|
||||
butFormat.Enable();
|
||||
file.Enable();
|
||||
seconds.Show();
|
||||
}
|
||||
void Stop() {
|
||||
player.Stop();
|
||||
seconds.SetText("0");
|
||||
sliderPosition.SetData(0);
|
||||
}
|
||||
void Pause() {
|
||||
player.Pause();
|
||||
}
|
||||
void Load() {
|
||||
if (!player.Load(~file)) {
|
||||
Exclamation(player.GetError());
|
||||
return;
|
||||
}
|
||||
Layout();
|
||||
int duration = int(player.GetDuration());
|
||||
if (duration <= 0)
|
||||
duration = 1;
|
||||
sliderPosition.MinMax(0, duration);
|
||||
if (duration < 20) {
|
||||
sliderPosition.SetMajorTicks(5);
|
||||
sliderPosition.SetMinorTicks(1);
|
||||
} else if (duration < 60) {
|
||||
sliderPosition.SetMajorTicks(10);
|
||||
sliderPosition.SetMinorTicks(5);
|
||||
} else if (duration < 60*10) {
|
||||
sliderPosition.SetMajorTicks(60);
|
||||
sliderPosition.SetMinorTicks(10);
|
||||
} else if (duration < 60*60) {
|
||||
sliderPosition.SetMajorTicks(10*60);
|
||||
sliderPosition.SetMinorTicks(5*60);
|
||||
} else {
|
||||
sliderPosition.SetMajorTicks(15*60);
|
||||
sliderPosition.SetMinorTicks(5*60);
|
||||
}
|
||||
sliderPosition.SetData(0);
|
||||
sliderPosition.Enable();
|
||||
butFormat.Enable();
|
||||
butPlay.Enable();
|
||||
butStop.Enable();
|
||||
butPause.Enable();
|
||||
}
|
||||
virtual void Close() {
|
||||
player.Stop();
|
||||
TopWindow::Close();
|
||||
}
|
||||
void BWEffect(SDLSurface &surface) {
|
||||
static int x, y;
|
||||
static bool left, up;
|
||||
int width = int(surface.GetWidth()/3);
|
||||
int height = int(surface.GetHeight()/3);
|
||||
int delta = 2;
|
||||
|
||||
if (!player.IsPaused()) {
|
||||
if (left)
|
||||
x -= delta;
|
||||
else
|
||||
x += delta;
|
||||
if (up)
|
||||
y -= delta;
|
||||
else
|
||||
y += delta;
|
||||
if (x < 0) {
|
||||
left = false;
|
||||
x = 1;
|
||||
} else if (x >= surface.GetWidth()-width) {
|
||||
left = true;
|
||||
x = surface.GetWidth()-width - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
up = false;
|
||||
y = 1;
|
||||
} else if (y >= surface.GetHeight()-height) {
|
||||
up = true;
|
||||
y = surface.GetHeight()-height - 1;
|
||||
}
|
||||
}
|
||||
for (int r = y; r < y+height; ++r) {
|
||||
for (int c = x; c < x+width; ++c) {
|
||||
byte bw = Grayscale(surface.GetPixel(c, r));
|
||||
surface.DrawPixel(c, r, Color(bw, bw, bw));
|
||||
}
|
||||
}
|
||||
surface.DrawRect(x, y, width, height, 1, Black());
|
||||
}
|
||||
void MotionDetect(SDLSurface &surface) {
|
||||
static Buffer <byte> img0;
|
||||
static Buffer <byte> img1;
|
||||
static bool which;
|
||||
static int prevLen;
|
||||
byte *prev, *actual;
|
||||
const int delta = 3;
|
||||
|
||||
int len = int(surface.GetWidth()*surface.GetHeight()/delta);
|
||||
if (len != prevLen) {
|
||||
img0.Alloc(len);
|
||||
img1.Alloc(len);
|
||||
}
|
||||
if (which) {
|
||||
prev = img0;
|
||||
actual = img1;
|
||||
which = false;
|
||||
} else {
|
||||
prev = img1;
|
||||
actual = img0;
|
||||
which = true;
|
||||
}
|
||||
|
||||
byte *preva, *actuala;
|
||||
actuala = actual;
|
||||
for (int r = 0; r < surface.GetHeight(); r+=delta) {
|
||||
for (int c = 0; c < surface.GetWidth(); c+=delta)
|
||||
*(actuala++) = Grayscale(surface.GetPixel(c, r));
|
||||
}
|
||||
if (len != prevLen) {
|
||||
prevLen = len;
|
||||
return;
|
||||
}
|
||||
actuala = actual;
|
||||
preva = prev;
|
||||
for (int r = 0; r < surface.GetHeight(); r+=delta) {
|
||||
for (int c = 0; c < surface.GetWidth(); c+=delta) {
|
||||
if (abs(*(actuala++) - *(preva++)) > 10)
|
||||
surface.FillRect(c, r, delta, delta, Blue());
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnFrame(SDLSurface &surface) {
|
||||
surface.Lock();
|
||||
if (blackWhite)
|
||||
BWEffect(surface);
|
||||
if (showLogo)
|
||||
surface.DrawImage(imLogo, 0, 0, Black());
|
||||
if (motionDetect)
|
||||
MotionDetect(surface);
|
||||
surface.Unlock();
|
||||
}
|
||||
void OnSecond() {
|
||||
double sec = player.GetSecond();
|
||||
secondsLabel.SetText(SecondsToString(int(sec), false));
|
||||
sliderPosition.SetData(int(sec));
|
||||
}
|
||||
void OnPause() {
|
||||
if (player.IsPaused()) {
|
||||
seconds.Show();
|
||||
seconds = SecondsToString(player.GetSecond(), false);
|
||||
} else
|
||||
seconds.Hide();
|
||||
}
|
||||
void OnSliderPosition() {
|
||||
player.SetSecond(int(~sliderPosition));
|
||||
seconds = SecondsToString(player.GetSecond(), false);
|
||||
}
|
||||
void OnSliderVolume() {
|
||||
player.SetAudioFactor(int(~sliderVolume)/100.);
|
||||
}
|
||||
void OnEditSeconds() {
|
||||
player.SetSecond(StringToSeconds(seconds));
|
||||
}
|
||||
void OnRgb() {
|
||||
player.SetRGB(rgb);
|
||||
motionDetect.Enable(rgb);
|
||||
showLogo.Enable(rgb);
|
||||
blackWhite.Enable(rgb);
|
||||
}
|
||||
void CheckOption(int ii, ArrayCtrl *arr) {
|
||||
int num = 0;
|
||||
for(int i = 0; i < arr->GetCount(); i++) {
|
||||
if (arr->Get(i, 0))
|
||||
num++;
|
||||
}
|
||||
if (num > 1) {
|
||||
Exclamation("It is possible to play only one stream");
|
||||
arr->Set(ii, 0, false);
|
||||
}
|
||||
}
|
||||
/*void OnFullScreen() {
|
||||
static Rect last;
|
||||
Close();
|
||||
if (IsFullScreen()) {
|
||||
FullScreen(false);
|
||||
SetRect(last);
|
||||
} else {
|
||||
last = GetRect();
|
||||
FullScreen(true);
|
||||
}
|
||||
OpenMain();
|
||||
}*/
|
||||
void FormatDialog() {
|
||||
WithFormat<TopWindow> format;
|
||||
|
||||
CtrlLayoutOK(format, "File format");
|
||||
format.duration.SetText(SecondsToString(player.GetDuration(), false));
|
||||
format.fileName.SetText(player.GetFileName());
|
||||
|
||||
format.arrVideo.SetLineCy(Draw::GetStdFontCy()+4);
|
||||
format.arrVideo.AddColumn("Sel");
|
||||
format.arrVideo.AddColumn("Codec");
|
||||
format.arrVideo.AddColumn("Pixel Format");
|
||||
format.arrVideo.AddColumn("Lang");
|
||||
format.arrVideo.AddColumn("Width");
|
||||
format.arrVideo.AddColumn("Height");
|
||||
format.arrVideo.AddColumn("PAR width");
|
||||
format.arrVideo.AddColumn("PAR height");
|
||||
format.arrVideo.AddColumn("DAR width");
|
||||
format.arrVideo.AddColumn("DAR height");
|
||||
format.arrVideo.AddColumn("Frame rate fps");
|
||||
format.arrVideo.AddColumn("Tbr");
|
||||
format.arrVideo.AddColumn("Tbn");
|
||||
format.arrVideo.AddColumn("Tbc");
|
||||
format.arrVideo.AddColumn("Bitrate kbps");
|
||||
format.arrVideo.AddColumn("Tags");
|
||||
format.arrVideo.ColumnWidths("30 100 70 40 45 45 60 60 60 60 80 50 50 50 70 80");
|
||||
format.arrVideo.AutoHideSb().HeaderObject().Absolute();
|
||||
|
||||
Array<Option> optionVideo;
|
||||
for (int i = 0; i < player.videoData.GetCount(); ++i) {
|
||||
format.arrVideo.Add(false, player.videoData[i].codec, player.videoData[i].pixFmt,
|
||||
player.videoData[i].lang,
|
||||
player.videoData[i].size.cx, player.videoData[i].size.cy,
|
||||
player.videoData[i].par.cx, player.videoData[i].par.cy,
|
||||
player.videoData[i].dar.cx, player.videoData[i].dar.cy,
|
||||
FormatDouble(player.videoData[i].frameRate.cx/double(player.videoData[i].frameRate.cy), 2),
|
||||
FormatDouble(player.videoData[i].tbr.cx/double(player.videoData[i].tbr.cy), 2),
|
||||
FormatDouble(player.videoData[i].tbn.cy/double(player.videoData[i].tbn.cx), 2),
|
||||
FormatDouble(player.videoData[i].tbc.cy/double(player.videoData[i].tbc.cx), 2),
|
||||
int(player.videoData[i].bitrate/1000),
|
||||
player.videoData[i].tags);
|
||||
Option &option = optionVideo.Add();
|
||||
format.arrVideo.SetCtrl(i, 0, option);
|
||||
option <<= THISBACK2(CheckOption, i, &format.arrVideo);
|
||||
}
|
||||
if (player.GetVideo() >= 0)
|
||||
format.arrVideo.Set(player.GetVideoId(), 0, true);
|
||||
|
||||
format.arrAudio.SetLineCy(Draw::GetStdFontCy()+4);
|
||||
format.arrAudio.AddColumn("Sel");
|
||||
format.arrAudio.AddColumn("Codec");
|
||||
format.arrAudio.AddColumn("Lang");
|
||||
format.arrAudio.AddColumn("Channels");
|
||||
format.arrAudio.AddColumn("Sample rate Hz");
|
||||
format.arrAudio.AddColumn("Bitrate kbps");
|
||||
format.arrAudio.AddColumn("Bits");
|
||||
format.arrAudio.AddColumn("Tags");
|
||||
format.arrAudio.ColumnWidths("30 100 40 60 90 70 40 100");
|
||||
format.arrAudio.AutoHideSb().HeaderObject().Absolute();
|
||||
|
||||
format.tags.NoEofLine();
|
||||
format.tags.SetData(player.GetTags());
|
||||
|
||||
Array<Option> optionAudio;
|
||||
for (int i = 0; i < player.audioData.GetCount(); ++i) {
|
||||
format.arrAudio.Add(false, player.audioData[i].codec, player.audioData[i].lang,
|
||||
player.audioData[i].channels,
|
||||
int64(player.audioData[i].sampleRate),
|
||||
int(player.audioData[i].bitrate/1000),
|
||||
player.audioData[i].bits,
|
||||
player.audioData[i].tags);
|
||||
Option &option = optionAudio.Add();
|
||||
format.arrAudio.SetCtrl(i, 0, option);
|
||||
option <<= THISBACK2(CheckOption, i, &format.arrAudio);
|
||||
}
|
||||
if (player.GetAudio() >= 0)
|
||||
format.arrAudio.Set(player.GetAudioId(), 0, true);
|
||||
|
||||
format.Sizeable();
|
||||
format.Execute();
|
||||
|
||||
int idVideo = -1;
|
||||
for (int i = 0; i < format.arrVideo.GetCount(); ++i) {
|
||||
if (format.arrVideo.Get(i, 0))
|
||||
idVideo = i;
|
||||
}
|
||||
player.SetVideoId(idVideo);
|
||||
|
||||
int idAudio = -1;
|
||||
for (int i = 0; i < format.arrAudio.GetCount(); ++i) {
|
||||
if (format.arrAudio.Get(i, 0))
|
||||
idAudio = i;
|
||||
}
|
||||
player.SetAudioId(idAudio);
|
||||
}
|
||||
void LabelFormatting(String &str, int val) {
|
||||
str = SecondsToString(val, false);
|
||||
}
|
||||
MediaPlayerDemo() {
|
||||
CtrlLayout(*this, "MediaPlayer demo");
|
||||
Zoomable().Sizeable();
|
||||
|
||||
butPlay.Disable();
|
||||
butPlay.WhenAction = THISBACK(Play);
|
||||
|
||||
butStop.Disable();
|
||||
butStop.WhenAction = THISBACK(Stop);
|
||||
|
||||
butPause.Disable();
|
||||
butPause.WhenAction = THISBACK(Pause);
|
||||
|
||||
butFormat.Disable();
|
||||
butFormat.WhenAction = THISBACK(FormatDialog);
|
||||
|
||||
file.WhenChange = THISBACK(Load);
|
||||
|
||||
forceAspect = true;
|
||||
forceAspect.WhenAction = THISBACK(OnForceAspect);
|
||||
|
||||
fullScreen = false;
|
||||
fullScreen.Disable();
|
||||
//fullScreen.WhenAction = THISBACK(OnFullScreen);
|
||||
|
||||
player.ForceAspect(forceAspect);
|
||||
player.WhenFrame = THISBACK(OnFrame);
|
||||
player.WhenSecond = THISBACK(OnSecond);
|
||||
player.WhenPause = THISBACK(OnPause);
|
||||
player.ShowAudio(true);
|
||||
|
||||
sliderPosition.MinMax(0, 100).SetMinorTicksSize(30).Jump(true);
|
||||
sliderPosition.SetData(0);
|
||||
sliderPosition.WhenAction = THISBACK(OnSliderPosition);
|
||||
sliderPosition.LabelFormat = THISBACK(LabelFormatting);
|
||||
sliderPosition.Enable(false);
|
||||
|
||||
sliderVolume.MinMax(0, 400).Jump(true);
|
||||
sliderVolume.SetData(100);
|
||||
|
||||
sliderVolume.WhenAction = THISBACK(OnSliderVolume);
|
||||
|
||||
seconds.WhenEnter = THISBACK(OnEditSeconds);
|
||||
seconds.SetText("0");
|
||||
|
||||
secondsLabel.SetText("0");
|
||||
|
||||
rgb = false;
|
||||
rgb.WhenAction = THISBACK(OnRgb);
|
||||
|
||||
motionDetect = false;
|
||||
motionDetect.Disable();
|
||||
|
||||
showLogo = false;
|
||||
showLogo.Disable();
|
||||
|
||||
blackWhite = false;
|
||||
blackWhite.Disable();
|
||||
|
||||
ImageDraw iwLogo(500, 100);
|
||||
iwLogo.DrawEllipse(20, 20, 100, 40, Brown());
|
||||
iwLogo.DrawText(46, 26, "U++", Arial(25).Bold(), Black());
|
||||
imLogo = iwLogo;
|
||||
}
|
||||
void OnForceAspect() {
|
||||
player.ForceAspect(forceAspect);
|
||||
}
|
||||
Image imLogo;
|
||||
};
|
||||
|
||||
void Run_MediaPlayer() {
|
||||
MediaPlayerDemo().Run();
|
||||
}
|
||||
|
||||
34
bazaar/MediaPlayer/demoMediaPlayer.lay
Normal file
34
bazaar/MediaPlayer/demoMediaPlayer.lay
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
LAYOUT(MainMediaPlayer, 320, 320)
|
||||
ITEM(Label, secondsLabel, SetFrame(FieldFrame()).RightPosZ(148, 56).BottomPosZ(69, 19))
|
||||
ITEM(Button, butPause, SetLabel(t_("Pause")).RightPosZ(52, 40).BottomPosZ(68, 20))
|
||||
ITEM(Button, butFormat, SetLabel(t_("Format")).RightPosZ(8, 40).BottomPosZ(28, 20))
|
||||
ITEM(Button, butPlay, SetLabel(t_("Play")).RightPosZ(96, 48).BottomPosZ(68, 20))
|
||||
ITEM(EditFile, file, HSizePosZ(4, 208).BottomPosZ(69, 19))
|
||||
ITEM(Option, blackWhite, SetLabel(t_("Grayscale effect")).LeftPosZ(188, 100).BottomPosZ(9, 19))
|
||||
ITEM(Option, motionDetect, SetLabel(t_("Motion detect")).LeftPosZ(96, 88).BottomPosZ(9, 19))
|
||||
ITEM(Option, showLogo, SetLabel(t_("Show logo")).LeftPosZ(188, 72).BottomPosZ(29, 19))
|
||||
ITEM(Option, rgb, SetLabel(t_("RGB/YUV")).LeftPosZ(96, 68).BottomPosZ(29, 19))
|
||||
ITEM(Option, fullScreen, SetLabel(t_("Full screen")).LeftPosZ(4, 88).BottomPosZ(9, 19))
|
||||
ITEM(Option, forceAspect, SetLabel(t_("Force aspect")).LeftPosZ(4, 88).BottomPosZ(29, 19))
|
||||
ITEM(EditString, seconds, RightPosZ(148, 56).BottomPosZ(69, 19))
|
||||
ITEM(SliderCtrlX, sliderPosition, HSizePosZ(4, 8).BottomPosZ(84, 40))
|
||||
ITEM(Button, butStop, SetLabel(t_("Stop")).RightPosZ(8, 40).BottomPosZ(68, 20))
|
||||
ITEM(MediaPlayer, player, SetFrame(InsetFrame()).HSizePosZ(4, 4).VSizePosZ(4, 124))
|
||||
ITEM(SliderCtrl, sliderVolume, RightPosZ(8, 80).BottomPosZ(40, 24))
|
||||
ITEM(VolumeCtrl, mainVolume, RightPosZ(88, 76).BottomPosZ(40, 24))
|
||||
END_LAYOUT
|
||||
|
||||
LAYOUT(Format, 400, 392)
|
||||
ITEM(ArrayCtrl, arrAudio, HSizePosZ(4, 4).TopPosZ(200, 100))
|
||||
ITEM(Label, dv___1, SetLabel(t_("Audio streams")).LeftPosZ(4, 104).TopPosZ(180, 19))
|
||||
ITEM(ArrayCtrl, arrVideo, HSizePosZ(4, 4).TopPosZ(68, 100))
|
||||
ITEM(Label, dv___3, SetLabel(t_("Video streams")).LeftPosZ(4, 104).TopPosZ(48, 19))
|
||||
ITEM(Label, fileName, SetFrame(ThinInsetFrame()).HSizePosZ(64, 4).TopPosZ(4, 19))
|
||||
ITEM(Label, dv___5, SetLabel(t_("File name:")).LeftPosZ(4, 60).TopPosZ(4, 19))
|
||||
ITEM(Label, duration, SetFrame(ThinInsetFrame()).LeftPosZ(64, 60).TopPosZ(24, 19))
|
||||
ITEM(Label, dv___7, SetLabel(t_("Duration:")).LeftPosZ(4, 60).TopPosZ(24, 19))
|
||||
ITEM(Button, ok, SetLabel(t_("Close")).RightPosZ(4, 64).BottomPosZ(4, 20))
|
||||
ITEM(DocEdit, tags, SetFrame(ThinInsetFrame()).WantFocus(false).SetEditable(false).HSizePosZ(4, 84).VSizePosZ(324, 4))
|
||||
ITEM(Label, dv___10, SetLabel(t_("Tags")).LeftPosZ(4, 30).TopPosZ(304, 19))
|
||||
END_LAYOUT
|
||||
|
||||
4
bazaar/MediaPlayer/demoVolumeCtrl..lay
Normal file
4
bazaar/MediaPlayer/demoVolumeCtrl..lay
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
LAYOUT(VolumeCtrlDemoLayout, 200, 100)
|
||||
ITEM(VolumeCtrl, volume, LeftPosZ(20, 140).TopPosZ(24, 32))
|
||||
END_LAYOUT
|
||||
|
||||
25
bazaar/MediaPlayer/demoVolumeCtrl.cpp
Normal file
25
bazaar/MediaPlayer/demoVolumeCtrl.cpp
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#include <Media/MediaPlayer.h>
|
||||
#include <Media/VolumeCtrl.h>
|
||||
|
||||
#define LAYOUTFILE <Media_demo/demoVolumeCtrl.lay>
|
||||
#include <CtrlCore/lay.h>
|
||||
|
||||
class VolumeCtrlDemo : public WithMainVolumeCtrl<TopWindow> {
|
||||
public:
|
||||
typedef VolumeCtrlDemo CLASSNAME;
|
||||
VolumeCtrlDemo();
|
||||
};
|
||||
|
||||
|
||||
VolumeCtrlDemo::VolumeCtrlDemo() {
|
||||
CtrlLayout(*this, "VolumeCtrl demo");
|
||||
Zoomable().Sizeable();
|
||||
}
|
||||
|
||||
void Run_VolumeCtrl() {
|
||||
VolumeCtrlDemo().Run();
|
||||
}
|
||||
7
bazaar/MediaPlayer/demoVolumeCtrl.lay
Normal file
7
bazaar/MediaPlayer/demoVolumeCtrl.lay
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
LAYOUT(MainVolumeCtrl, 276, 260)
|
||||
ITEM(VolumeCtrl, dv___0, SetStereo(true).SetFrame(ThinInsetFrame()).HSizePosZ(220, 4).VSizePosZ(68, 64))
|
||||
ITEM(VolumeCtrl, dv___1, SetStereo(true).SetFrame(ThinInsetFrame()).HSizePosZ(8, 4).BottomPosZ(4, 56))
|
||||
ITEM(Label, dv___2, SetLabel(t_("Move the controls to change L and R speakers\nmain volume.\nOpen PC volume controls to test it.")).SetFont(StdFontZ(12)).LeftPosZ(4, 268).TopPosZ(4, 56))
|
||||
ITEM(VolumeCtrl, dv___3, SetStereo(true).SetFrame(ThinInsetFrame()).LeftPosZ(8, 204).VSizePosZ(68, 136))
|
||||
END_LAYOUT
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef _MediaPlayer_icpp_init_stub
|
||||
#define _MediaPlayer_icpp_init_stub
|
||||
#ifndef _Media_Demo_icpp_init_stub
|
||||
#define _Media_Demo_icpp_init_stub
|
||||
#include "CtrlLib/init"
|
||||
#include "Controls4U/init"
|
||||
#include "GridCtrl/init"
|
||||
|
|
|
|||
|
|
@ -1,382 +1,36 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
#include <GridCtrl/GridCtrl.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#include <Media/MediaPlayer.h>
|
||||
#include <Controls4U/Controls4U.h>
|
||||
#include <SliderCtrlX/SliderCtrlX.h>
|
||||
|
||||
#define LAYOUTFILE <MediaPlayer/demo.lay>
|
||||
#define LAYOUTFILE <Media_demo/demo.lay>
|
||||
#include <CtrlCore/lay.h>
|
||||
|
||||
bool Demo();
|
||||
void Run_MediaPlayer();
|
||||
void Run_VolumeCtrl();
|
||||
|
||||
struct MediaPlayerDemo : public WithMain<TopWindow> {
|
||||
typedef MediaPlayerDemo CLASSNAME;
|
||||
void Play() {
|
||||
butPlay.Disable();
|
||||
butPause.Enable();
|
||||
butStop.Enable();
|
||||
butFormat.Disable();
|
||||
file.Disable();
|
||||
seconds.Hide();
|
||||
secondsLabel.SetText("0");
|
||||
slider.SetData(0);
|
||||
|
||||
if (!player.Play())
|
||||
Exclamation(player.GetError());
|
||||
|
||||
seconds.SetText("0");
|
||||
slider.SetData(0);
|
||||
butPlay.Enable();
|
||||
butPause.Disable();
|
||||
butStop.Disable();
|
||||
butFormat.Enable();
|
||||
file.Enable();
|
||||
seconds.Show();
|
||||
struct Media_Demo : public WithMain<TopWindow> {
|
||||
typedef Media_Demo CLASSNAME;
|
||||
void OnRun() {
|
||||
String demo = grid.Get(0);
|
||||
if (demo == "MediaPlayer")
|
||||
Run_MediaPlayer();
|
||||
else if (demo == "VolumeCtrl")
|
||||
Run_VolumeCtrl();
|
||||
}
|
||||
void Stop() {
|
||||
player.Stop();
|
||||
seconds.SetText("0");
|
||||
slider.SetData(0);
|
||||
}
|
||||
void Pause() {
|
||||
player.Pause();
|
||||
}
|
||||
void Load() {
|
||||
if (!player.Load(~file)) {
|
||||
Exclamation(player.GetError());
|
||||
return;
|
||||
}
|
||||
Layout();
|
||||
int duration = int(player.GetDuration());
|
||||
if (duration <= 0)
|
||||
duration = 1;
|
||||
slider.MinMax(0, duration);
|
||||
if (duration < 20) {
|
||||
slider.SetMajorTicks(5);
|
||||
slider.SetMinorTicks(1);
|
||||
} else if (duration < 60) {
|
||||
slider.SetMajorTicks(10);
|
||||
slider.SetMinorTicks(5);
|
||||
} else if (duration < 60*10) {
|
||||
slider.SetMajorTicks(60);
|
||||
slider.SetMinorTicks(10);
|
||||
} else if (duration < 60*60) {
|
||||
slider.SetMajorTicks(10*60);
|
||||
slider.SetMinorTicks(5*60);
|
||||
} else {
|
||||
slider.SetMajorTicks(15*60);
|
||||
slider.SetMinorTicks(5*60);
|
||||
}
|
||||
slider.SetData(0);
|
||||
slider.Enable(true);
|
||||
}
|
||||
virtual void Close() {
|
||||
player.Stop();
|
||||
TopWindow::Close();
|
||||
}
|
||||
void BWEffect(SDLSurface &surface) {
|
||||
static int x, y;
|
||||
static bool left, up;
|
||||
int width = int(surface.GetWidth()/3);
|
||||
int height = int(surface.GetHeight()/3);
|
||||
int delta = 2;
|
||||
Media_Demo() {
|
||||
CtrlLayout(*this, "Media Examples");
|
||||
|
||||
if (!player.IsPaused()) {
|
||||
if (left)
|
||||
x -= delta;
|
||||
else
|
||||
x += delta;
|
||||
if (up)
|
||||
y -= delta;
|
||||
else
|
||||
y += delta;
|
||||
if (x < 0) {
|
||||
left = false;
|
||||
x = 1;
|
||||
} else if (x >= surface.GetWidth()-width) {
|
||||
left = true;
|
||||
x = surface.GetWidth()-width - 1;
|
||||
}
|
||||
if (y < 0) {
|
||||
up = false;
|
||||
y = 1;
|
||||
} else if (y >= surface.GetHeight()-height) {
|
||||
up = true;
|
||||
y = surface.GetHeight()-height - 1;
|
||||
}
|
||||
}
|
||||
for (int r = y; r < y+height; ++r) {
|
||||
for (int c = x; c < x+width; ++c) {
|
||||
byte bw = Grayscale(surface.GetPixel(c, r));
|
||||
surface.DrawPixel(c, r, Color(bw, bw, bw));
|
||||
}
|
||||
}
|
||||
surface.DrawRect(x, y, width, height, 1, Black());
|
||||
butRun.WhenAction = THISBACK(OnRun);
|
||||
|
||||
grid.AddColumn("Demo", 20);
|
||||
grid.AddColumn("Description", 60);
|
||||
grid.Add("MediaPlayer", "MediaPlayer control demo");
|
||||
grid.Add("VolumeCtrl", "Simple VolumeCtrl control demo");
|
||||
grid.SetLineCy(int(1.4*StdFont().GetCy()));
|
||||
grid.WhenLeftDouble = THISBACK(OnRun);
|
||||
}
|
||||
void MotionDetect(SDLSurface &surface) {
|
||||
static Buffer <byte> img0;
|
||||
static Buffer <byte> img1;
|
||||
static bool which;
|
||||
static int prevLen;
|
||||
byte *prev, *actual;
|
||||
const int delta = 3;
|
||||
|
||||
int len = int(surface.GetWidth()*surface.GetHeight()/delta);
|
||||
if (len != prevLen) {
|
||||
img0.Alloc(len);
|
||||
img1.Alloc(len);
|
||||
}
|
||||
if (which) {
|
||||
prev = img0;
|
||||
actual = img1;
|
||||
which = false;
|
||||
} else {
|
||||
prev = img1;
|
||||
actual = img0;
|
||||
which = true;
|
||||
}
|
||||
|
||||
byte *preva, *actuala;
|
||||
actuala = actual;
|
||||
for (int r = 0; r < surface.GetHeight(); r+=delta) {
|
||||
for (int c = 0; c < surface.GetWidth(); c+=delta)
|
||||
*(actuala++) = Grayscale(surface.GetPixel(c, r));
|
||||
}
|
||||
if (len != prevLen) {
|
||||
prevLen = len;
|
||||
return;
|
||||
}
|
||||
actuala = actual;
|
||||
preva = prev;
|
||||
for (int r = 0; r < surface.GetHeight(); r+=delta) {
|
||||
for (int c = 0; c < surface.GetWidth(); c+=delta) {
|
||||
if (abs(*(actuala++) - *(preva++)) > 10)
|
||||
surface.FillRect(c, r, delta, delta, Blue());
|
||||
}
|
||||
}
|
||||
}
|
||||
void OnFrame(SDLSurface &surface) {
|
||||
surface.Lock();
|
||||
if (blackWhite)
|
||||
BWEffect(surface);
|
||||
if (showLogo)
|
||||
surface.DrawImage(imLogo, 0, 0, Black());
|
||||
if (motionDetect)
|
||||
MotionDetect(surface);
|
||||
surface.Unlock();
|
||||
}
|
||||
void OnSecond() {
|
||||
double sec = player.GetSecond();
|
||||
secondsLabel.SetText(SecondsToString(int(sec), false));
|
||||
slider.SetData(int(sec));
|
||||
}
|
||||
void OnPause() {
|
||||
if (player.IsPaused()) {
|
||||
seconds.Show();
|
||||
seconds = SecondsToString(player.GetSecond(), false);
|
||||
} else
|
||||
seconds.Hide();
|
||||
}
|
||||
void OnSlider() {
|
||||
player.SetSecond(int(~slider));
|
||||
seconds = SecondsToString(player.GetSecond(), false);
|
||||
}
|
||||
void OnEditSeconds() {
|
||||
player.SetSecond(StringToSeconds(seconds));
|
||||
}
|
||||
void OnRgb() {
|
||||
player.SetRGB(rgb);
|
||||
motionDetect.Enable(rgb);
|
||||
showLogo.Enable(rgb);
|
||||
blackWhite.Enable(rgb);
|
||||
}
|
||||
void CheckOption(int ii, ArrayCtrl *arr) {
|
||||
int num = 0;
|
||||
for(int i = 0; i < arr->GetCount(); i++) {
|
||||
if (arr->Get(i, 0))
|
||||
num++;
|
||||
}
|
||||
if (num > 1) {
|
||||
Exclamation("It is possible to play only one stream");
|
||||
arr->Set(ii, 0, false);
|
||||
}
|
||||
}
|
||||
/*void OnFullScreen() {
|
||||
static Rect last;
|
||||
Close();
|
||||
if (IsFullScreen()) {
|
||||
FullScreen(false);
|
||||
SetRect(last);
|
||||
} else {
|
||||
last = GetRect();
|
||||
FullScreen(true);
|
||||
}
|
||||
OpenMain();
|
||||
}*/
|
||||
void FormatDialog() {
|
||||
WithFormat<TopWindow> format;
|
||||
|
||||
CtrlLayoutOK(format, "File format");
|
||||
format.duration.SetText(SecondsToString(player.GetDuration(), false));
|
||||
format.fileName.SetText(player.GetFileName());
|
||||
|
||||
format.arrVideo.SetLineCy(Draw::GetStdFontCy()+4);
|
||||
format.arrVideo.AddColumn("Sel");
|
||||
format.arrVideo.AddColumn("Codec");
|
||||
format.arrVideo.AddColumn("Pixel Format");
|
||||
format.arrVideo.AddColumn("Lang");
|
||||
format.arrVideo.AddColumn("Width");
|
||||
format.arrVideo.AddColumn("Height");
|
||||
format.arrVideo.AddColumn("PAR width");
|
||||
format.arrVideo.AddColumn("PAR height");
|
||||
format.arrVideo.AddColumn("DAR width");
|
||||
format.arrVideo.AddColumn("DAR height");
|
||||
format.arrVideo.AddColumn("Frame rate fps");
|
||||
format.arrVideo.AddColumn("Tbr");
|
||||
format.arrVideo.AddColumn("Tbn");
|
||||
format.arrVideo.AddColumn("Tbc");
|
||||
format.arrVideo.AddColumn("Bitrate kbps");
|
||||
format.arrVideo.AddColumn("Tags");
|
||||
format.arrVideo.ColumnWidths("30 100 70 40 45 45 60 60 60 60 80 50 50 50 70 80");
|
||||
format.arrVideo.AutoHideSb().HeaderObject().Absolute();
|
||||
|
||||
Array<Option> optionVideo;
|
||||
for (int i = 0; i < player.videoData.GetCount(); ++i) {
|
||||
format.arrVideo.Add(false, player.videoData[i].codec, player.videoData[i].pixFmt,
|
||||
player.videoData[i].lang,
|
||||
player.videoData[i].size.cx, player.videoData[i].size.cy,
|
||||
player.videoData[i].par.cx, player.videoData[i].par.cy,
|
||||
player.videoData[i].dar.cx, player.videoData[i].dar.cy,
|
||||
FormatDouble(player.videoData[i].frameRate.cx/double(player.videoData[i].frameRate.cy), 2),
|
||||
FormatDouble(player.videoData[i].tbr.cx/double(player.videoData[i].tbr.cy), 2),
|
||||
FormatDouble(player.videoData[i].tbn.cy/double(player.videoData[i].tbn.cx), 2),
|
||||
FormatDouble(player.videoData[i].tbc.cy/double(player.videoData[i].tbc.cx), 2),
|
||||
int(player.videoData[i].bitrate/1000),
|
||||
player.videoData[i].tags);
|
||||
Option &option = optionVideo.Add();
|
||||
format.arrVideo.SetCtrl(i, 0, option);
|
||||
option <<= THISBACK2(CheckOption, i, &format.arrVideo);
|
||||
}
|
||||
if (player.GetVideo() >= 0)
|
||||
format.arrVideo.Set(player.GetVideoId(), 0, true);
|
||||
|
||||
format.arrAudio.SetLineCy(Draw::GetStdFontCy()+4);
|
||||
format.arrAudio.AddColumn("Sel");
|
||||
format.arrAudio.AddColumn("Codec");
|
||||
format.arrAudio.AddColumn("Lang");
|
||||
format.arrAudio.AddColumn("Channels");
|
||||
format.arrAudio.AddColumn("Sample rate Hz");
|
||||
format.arrAudio.AddColumn("Bitrate kbps");
|
||||
format.arrAudio.AddColumn("Bits");
|
||||
format.arrAudio.AddColumn("Tags");
|
||||
format.arrAudio.ColumnWidths("30 100 40 60 90 70 40 100");
|
||||
format.arrAudio.AutoHideSb().HeaderObject().Absolute();
|
||||
|
||||
format.tags.NoEofLine();
|
||||
format.tags.SetData(player.GetTags());
|
||||
|
||||
Array<Option> optionAudio;
|
||||
for (int i = 0; i < player.audioData.GetCount(); ++i) {
|
||||
format.arrAudio.Add(false, player.audioData[i].codec, player.audioData[i].lang,
|
||||
player.audioData[i].channels,
|
||||
int64(player.audioData[i].sampleRate),
|
||||
int(player.audioData[i].bitrate/1000),
|
||||
player.audioData[i].bits,
|
||||
player.audioData[i].tags);
|
||||
Option &option = optionAudio.Add();
|
||||
format.arrAudio.SetCtrl(i, 0, option);
|
||||
option <<= THISBACK2(CheckOption, i, &format.arrAudio);
|
||||
}
|
||||
if (player.GetAudio() >= 0)
|
||||
format.arrAudio.Set(player.GetAudioId(), 0, true);
|
||||
|
||||
format.Sizeable();
|
||||
format.Execute();
|
||||
|
||||
int idVideo = -1;
|
||||
for (int i = 0; i < format.arrVideo.GetCount(); ++i) {
|
||||
if (format.arrVideo.Get(i, 0))
|
||||
idVideo = i;
|
||||
}
|
||||
player.SetVideoId(idVideo);
|
||||
|
||||
int idAudio = -1;
|
||||
for (int i = 0; i < format.arrAudio.GetCount(); ++i) {
|
||||
if (format.arrAudio.Get(i, 0))
|
||||
idAudio = i;
|
||||
}
|
||||
player.SetAudioId(idAudio);
|
||||
}
|
||||
void LabelFormatting(String &str, int val) {
|
||||
str = SecondsToString(val, false);
|
||||
}
|
||||
MediaPlayerDemo() {
|
||||
CtrlLayout(*this, "MediaPlayer demo");
|
||||
Zoomable().Sizeable();
|
||||
|
||||
butPlay.WhenAction = THISBACK(Play);
|
||||
butStop.WhenAction = THISBACK(Stop);
|
||||
butPause.WhenAction = THISBACK(Pause);
|
||||
butStop.Disable();
|
||||
butFormat.WhenAction = THISBACK(FormatDialog);
|
||||
|
||||
file.WhenChange = THISBACK(Load);
|
||||
|
||||
forceAspect = true;
|
||||
forceAspect.WhenAction = THISBACK(OnForceAspect);
|
||||
|
||||
fullScreen = false;
|
||||
fullScreen.Disable();
|
||||
//fullScreen.WhenAction = THISBACK(OnFullScreen);
|
||||
|
||||
player.ForceAspect(forceAspect);
|
||||
player.WhenFrame = THISBACK(OnFrame);
|
||||
player.WhenSecond = THISBACK(OnSecond);
|
||||
player.WhenPause = THISBACK(OnPause);
|
||||
player.ShowAudio(true);
|
||||
|
||||
slider.MinMax(0, 100).SetMinorTicksSize(30).Jump(true);
|
||||
slider.SetData(0);
|
||||
slider.WhenAction = THISBACK(OnSlider);
|
||||
slider.LabelFormat = THISBACK(LabelFormatting);
|
||||
slider.Enable(false);
|
||||
|
||||
seconds.WhenEnter = THISBACK(OnEditSeconds);
|
||||
seconds.SetText("0");
|
||||
|
||||
secondsLabel.SetText("0");
|
||||
|
||||
rgb = false;
|
||||
rgb.WhenAction = THISBACK(OnRgb);
|
||||
|
||||
motionDetect = false;
|
||||
motionDetect.Disable();
|
||||
|
||||
showLogo = false;
|
||||
showLogo.Disable();
|
||||
|
||||
blackWhite = false;
|
||||
blackWhite.Disable();
|
||||
|
||||
ImageDraw iwLogo(500, 100);
|
||||
iwLogo.DrawEllipse(20, 20, 100, 40, Brown());
|
||||
iwLogo.DrawText(46, 26, "U++", Arial(25).Bold(), Black());
|
||||
imLogo = iwLogo;
|
||||
}
|
||||
void OnForceAspect() {
|
||||
player.ForceAspect(forceAspect);
|
||||
}
|
||||
Image imLogo;
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
MediaPlayerDemo app;
|
||||
app.OpenMain();
|
||||
Ctrl::EventLoop();
|
||||
app.Close();
|
||||
GUI_APP_MAIN {
|
||||
Media_Demo().Run();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
topic "MediaPlayer";
|
||||
topic "Media_demo";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[a83;*R6 $$1,0#31310162474203024125188417583966:caption]
|
||||
[{_}%EN-US
|
||||
[s1; [+184 MediaPlayer]&]
|
||||
[s0; [2 MediaPlayer package is a demo of MediaPlayer control.]&]
|
||||
[s1; [+184 Media`_demo]&]
|
||||
[s0; [2 Media`_demo package is a demo of Media controls.]&]
|
||||
[s0;2 &]
|
||||
[s0;2 &]
|
||||
[s0; [*2 MediaPlayer demo]&]
|
||||
[s0;2 &]
|
||||
[s0; [2 It demonstrates MediaPlayer control.]&]
|
||||
[s0;2 &]
|
||||
[s0; [2 In addition to play, pause and stop, other options included
|
||||
are:]&]
|
||||
|
|
@ -4483,4 +4488,9 @@ has been detected.]&]
|
|||
åœØ»ÆÙ¤‚»Ïãóæü–¸¶•µÄ•¸˜ßáëâåéÙšÇùœ÷½<EFBFBD>¬ÎýŽ»µ¼ƒèÞÄ·„ÿˆŠÎú±˜úѺʉû‹²óâÄìæøÑ³ß›»óý¨Ø
|
||||
îÙ<EFBFBD>·‹¹–îÔû§¢³ŸŠŒ³•Û¹’¯Î㥽宬âËÙñ¹–¸<EFBFBD>–á뻞Ï÷ñ<EFBFBD>è‚Ñÿ¨ª¸ó°ú¸ÈÀÀ<EFBFBD>Œüß<EFBFBD>Òé«©
|
||||
]&]
|
||||
[s0;2 &]
|
||||
[s0;2 &]
|
||||
[s0; [*2 VolumeCtrl]&]
|
||||
[s0;2 &]
|
||||
[s0; [2 It demonstrates VolumeCtrl.]&]
|
||||
[s0; ]
|
||||
Loading…
Add table
Add a link
Reference in a new issue