fix conflicts

This commit is contained in:
[CST] Focus
2012-03-20 11:14:05 +04:00
25 changed files with 820 additions and 354 deletions

View File

@@ -35,7 +35,8 @@ libneutrino_driver_a_SOURCES = \
radiotext.cpp \
fade.cpp \
screenshot.cpp \
ringbuffer.c
ringbuffer.c \
volume.cpp
if BOXTYPE_COOL
libneutrino_driver_a_SOURCES += \

View File

@@ -292,6 +292,8 @@ return 0;
upper = halflinegap+ascender+3; // we add 3 at top
lower = -descender+halflinegap+1; // we add 1 at bottom
height=upper+lower; // this is total height == distance of lines
DigitHeight = ascender+2;
DigitOffset = -descender+halflinegap;
// hack end
//printf("glyph: hM=%d tM=%d hg=%d tg=%d ascender=%d descender=%d height=%d linegap/2=%d upper=%d lower=%d\n",
@@ -310,6 +312,16 @@ int Font::getHeight(void)
return height;
}
int Font::getDigitHeight(void)
{
return DigitHeight;
}
int Font::getDigitOffset(void)
{
return DigitOffset;
}
int UTF8ToUnicode(const char * &text, const bool utf8_encoded) // returns -1 on error
{
int unicode_value;

View File

@@ -51,7 +51,7 @@ class Font
FT_Error getGlyphBitmap(FT_ULong glyph_index, FTC_SBit *sbit);
// these are HACKED values, because the font metrics were unusable.
int height,ascender,descender,upper,lower;
int height,DigitHeight,DigitOffset,ascender,descender,upper,lower;
int fontwidth;
public:
@@ -68,6 +68,8 @@ class Font
int getRenderWidth(const char * text, const bool utf8_encoded = false);
int getRenderWidth(const std::string & text, const bool utf8_encoded = false);
int getHeight(void);
int getDigitHeight(void);
int getDigitOffset(void);
int getWidth(void);
int getSize(){return font.width;}
int setSize(int isize);

View File

@@ -179,6 +179,10 @@ CFrameBuffer::CFrameBuffer()
backgroundFilename = "";
fd = 0;
tty = 0;
m_transparent_default = CFrameBuffer::TM_BLACK; // TM_BLACK: Transparency when black content ('pseudo' transparency)
// TM_NONE: No 'pseudo' transparency
// TM_INI: Transparency depends on g_settings.infobar_alpha ???
m_transparent = m_transparent_default;
//FIXME: test
memset(red, 0, 256*sizeof(__u16));
memset(green, 0, 256*sizeof(__u16));
@@ -292,6 +296,7 @@ printf("smem_start %x\n", smem_start);
paletteSet();
useBackground(false);
m_transparent = m_transparent_default;
#if 0
if ((tty=open("/dev/vc/0", O_RDWR))<0) {
perror("open (tty)");
@@ -1627,27 +1632,36 @@ void * CFrameBuffer::int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x,
unsigned long count = x * y;
fbbuff = (unsigned int *) cs_malloc_uncached(count * sizeof(unsigned int));
if(fbbuff == NULL)
{
if(fbbuff == NULL) {
printf("convertRGB2FB%s: Error: cs_malloc_uncached\n", ((alpha) ? " (Alpha)" : ""));
return NULL;
}
if (alpha)
{
if (alpha) {
for(i = 0; i < count ; i++)
fbbuff[i] = ((rgbbuff[i*4+3] << 24) & 0xFF000000) |
((rgbbuff[i*4] << 16) & 0x00FF0000) |
((rgbbuff[i*4+1] << 8) & 0x0000FF00) |
((rgbbuff[i*4+2]) & 0x000000FF);
}else
{
for(i = 0; i < count ; i++)
{
transp = 0;
if(rgbbuff[i*3] || rgbbuff[i*3+1] || rgbbuff[i*3+2])
transp = 0xFF;
fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF);
} else {
switch (m_transparent) {
case CFrameBuffer::TM_BLACK:
for(i = 0; i < count ; i++) {
transp = 0;
if(rgbbuff[i*3] || rgbbuff[i*3+1] || rgbbuff[i*3+2])
transp = 0xFF;
fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF);
}
break;
case CFrameBuffer::TM_INI:
for(i = 0; i < count ; i++)
fbbuff[i] = (transp << 24) | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF);
break;
case CFrameBuffer::TM_NONE:
default:
for(i = 0; i < count ; i++)
fbbuff[i] = 0xFF000000 | ((rgbbuff[i*3] << 16) & 0xFF0000) | ((rgbbuff[i*3+1] << 8) & 0xFF00) | (rgbbuff[i*3+2] & 0xFF);
break;
}
}
return (void *) fbbuff;
@@ -1744,3 +1758,18 @@ void CFrameBuffer::displayRGB(unsigned char *rgbbuff, int x_size, int y_size, in
blit2FB(fbbuff, x_size, y_size, x_offs, y_offs, x_pan, y_pan);
cs_free_uncached(fbbuff);
}
void CFrameBuffer::paintMuteIcon(bool paint, int ax, int ay, int dx, int dy, bool paintFrame)
{
if(paint) {
if (paintFrame) {
paintBackgroundBoxRel(ax, ay, dx, dy);
paintBoxRel(ax, ay, dx, dy, COL_MENUCONTENT_PLUS_0, RADIUS_SMALL);
}
int icon_dx=0, icon_dy=0;
getIconSize(NEUTRINO_ICON_BUTTON_MUTE, &icon_dx, &icon_dy);
paintIcon(NEUTRINO_ICON_BUTTON_MUTE, ax+((dx-icon_dx)/2), ay+((dy-icon_dy)/2));
}
else
paintBackgroundBoxRel(ax, ay, dx, dy);
}

View File

@@ -114,6 +114,7 @@ class CFrameBuffer
std::map<std::string, rawIcon> icon_cache;
int cache_size;
void * int_convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp, bool alpha);
int m_transparent_default, m_transparent;
public:
fb_pixel_t realcolor[256];
@@ -221,7 +222,17 @@ class CFrameBuffer
void displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb = true, int transp = 0xFF);
void blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp = 0, uint32_t yp = 0, bool transp = false);
bool blitToPrimary(unsigned int * data, int dx, int dy, int sw, int sh);
void paintMuteIcon(bool paint, int ax, int ay, int dx, int dy, bool paintFrame=true);
enum
{
TM_EMPTY = 0,
TM_NONE = 1,
TM_BLACK = 2,
TM_INI = 3
};
void SetTransparent(int t){ m_transparent = t; }
void SetTransparentDefault(){ m_transparent = m_transparent_default; }
};
#endif

View File

@@ -547,25 +547,19 @@ void CPictureViewer::rescaleImageDimensions(int *width, int *height, const int m
}
}
bool CPictureViewer::DisplayImage (const std::string & name, int posx, int posy, int width, int height)
bool CPictureViewer::DisplayImage(const std::string & name, int posx, int posy, int width, int height, int transp)
{
return int_DisplayImage(name, posx, posy, width, height, false);
}
CFrameBuffer* frameBuffer = CFrameBuffer::getInstance();
if (transp > CFrameBuffer::TM_EMPTY)
frameBuffer->SetTransparent(transp);
bool CPictureViewer::DisplayImage(const std::string & name, int posx, int posy, int width, int height, const fb_pixel_t colBg)
{
return int_DisplayImage(name, posx, posy, width, height, true, colBg);
}
bool CPictureViewer::int_DisplayImage(const std::string & name, int posx, int posy, int width, int height, bool paintBg, const fb_pixel_t colBg)
{
/* TODO: cache or check for same */
fb_pixel_t * data = getImage(name, width, height);
if (transp > CFrameBuffer::TM_EMPTY)
frameBuffer->SetTransparentDefault();
if(data) {
CFrameBuffer* frameBuffer = CFrameBuffer::getInstance();
if (paintBg)
frameBuffer->paintBoxRel(posx, posy, width, height, colBg);
frameBuffer->blit2FB(data, width, height, posx, posy);
cs_free_uncached(data);
return true;

View File

@@ -63,8 +63,7 @@ class CPictureViewer
void Cleanup();
void SetVisible(int startx, int endx, int starty, int endy);
static double m_aspect_ratio_correction;
bool DisplayImage (const std::string & name, int posx, int posy, int width, int height);
bool DisplayImage (const std::string & name, int posx, int posy, int width, int height, const fb_pixel_t colBg);
bool DisplayImage (const std::string & name, int posx, int posy, int width, int height, int transp=CFrameBuffer::TM_EMPTY);
bool DisplayLogo (uint64_t channel_id, int posx, int posy, int width, int height);
bool GetLogoName(uint64_t channel_id, std::string ChanName, std::string & name, int *width = NULL, int *height = NULL);
fb_pixel_t * getImage (const std::string & name, int width, int height);
@@ -112,7 +111,6 @@ class CPictureViewer
void add_format(int (*picsize)(const char *,int *,int*,int,int),int (*picread)(const char *,unsigned char **,int*,int*), int (*id)(const char*));
unsigned char * int_Resize(unsigned char *orgin, int ox, int oy, int dx, int dy, ScalingMode type, unsigned char * dst, bool alpha);
fb_pixel_t * int_getImage(const std::string & name, int *width, int *height, bool GetImage);
bool int_DisplayImage (const std::string & name, int posx, int posy, int width, int height, bool paintBg, const fb_pixel_t colBg=0);
};

327
src/driver/volume.cpp Normal file
View File

@@ -0,0 +1,327 @@
/*
volume bar - Neutrino-GUI
Copyright (C) 2001 Steffen Hehn 'McClean'
and some other guys
Homepage: http://dbox.cyberphoria.org/
Copyright (C) 2011-2012 M. Liebmann (micha-bbg)
License: GPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <global.h>
#include <neutrino.h>
#include <gui/infoclock.h>
#include <gui/keybind_setup.h>
#include <system/debug.h>
#include <audio_cs.h>
#include <system/settings.h>
#include <daemonc/remotecontrol.h>
#include <driver/framebuffer.h>
#include <driver/volume.h>
#if HAVE_COOL_HARDWARE
#include <gui/widget/progressbar.h>
#endif
CFrameBuffer * frameBuffer;
CRemoteControl * v_RemoteControl;
extern cAudio * audioDecoder;
static CProgressBar *g_volscale = NULL;
CVolume::CVolume()
{
frameBuffer = CFrameBuffer::getInstance();
g_Zapit = new CZapitClient;
g_RCInput = new CRCInput;
v_RemoteControl = new CRemoteControl;
VolumeFont = SNeutrinoSettings::FONT_TYPE_INFOBAR_INFO;
paintDigits = true; // For future On/Off digits
paintShadow = false; // For future On/Off switch shadow
MuteIconFrame = false; // For future On/Off switch IconFrame
ShadowOffset = 4;
mute_ay = 0;
Init();
}
CVolume::~CVolume()
{
if (g_volscale)
delete g_volscale;
}
void CVolume::Init()
{
mute_ay_old = mute_ay;
int faktor_h = 18; // scale * 10
int clock_height= 0;
int clock_width = 0;
int x_corr = 0;
pB = 2; // progress border
spacer = 8;
colBar = COL_MENUCONTENT_PLUS_0;
colFrame = COL_MENUCONTENT_PLUS_3;
colContent = COL_MENUCONTENT;
colShadow = COL_MENUCONTENTDARK_PLUS_0;
x = frameBuffer->getScreenX();
y = sy = frameBuffer->getScreenY() + spacer / 2;
sw = g_settings.screen_EndX - spacer;
sh = frameBuffer->getScreenHeight();
frameBuffer->getIconSize(NEUTRINO_ICON_VOLUME, &icon_w, &icon_h);
vbar_h = std::max((icon_h * faktor_h) / 10, digit_h+digit_offset);
progress_h = icon_h - 2*pB;
progress_w = 200;
vbar_w = spacer + icon_w + spacer + progress_w + spacer;
if (paintDigits) {
digit_w = g_Font[VolumeFont]->getRenderWidth("100");
digit_offset = g_Font[VolumeFont]->getDigitOffset();
digit_h = g_Font[VolumeFont]->getDigitHeight();
progress_h = std::max(icon_h, digit_h) - 2*pB;
vbar_w += digit_w;
}
g_volscale = new CProgressBar(true, progress_w, progress_h, 50, 100, 80, true);
// mute icon
mute_icon_dx = 0;
mute_icon_dy = 0;
frameBuffer->getIconSize(NEUTRINO_ICON_BUTTON_MUTE, &mute_icon_dx, &mute_icon_dy);
mute_dx = mute_icon_dx;
mute_dy = mute_icon_dy;
mute_dx += mute_icon_dx / 4;
mute_dy += mute_icon_dx / 4;
mute_ax = sw - mute_dx;
mute_ay = y;
if ((g_settings.mode_clock) && (g_settings.volume_pos == 0)) {
// Clock and MuteIcon in a line.
clock_height = CInfoClock::getInstance(true)->time_height;
clock_width = CInfoClock::getInstance(true)->time_width;
mute_ay += (clock_height - mute_dy) / 2;
}
else {
// Volume level and MuteIcon in a line.
if (mute_dy > vbar_h)
y += (mute_dy - vbar_h) / 2;
else
mute_ay += (vbar_h - mute_dy) / 2;
}
if ((g_settings.mode_clock) && (!CNeutrinoApp::getInstance()->isMuted()))
frameBuffer->paintBackgroundBoxRel(sw - clock_width, y, clock_width, clock_height);
//printf("\n##### [volume.cpp Zeile %d] mute_ax %d, mute_dx %d\n \n", __LINE__, mute_ax, mute_dx);
switch (g_settings.volume_pos)
{
case 0:// upper right
if (CNeutrinoApp::getInstance()->isMuted())
x_corr = mute_dx + spacer;
x = sw - vbar_w - x_corr;
if (g_settings.mode_clock)
y += clock_height + spacer / 2;
break;
case 1:// upper left
break;
case 2:// bottom left
y = sh - vbar_h;
break;
case 3:// bottom right
x = sw - vbar_w;
y = sh - vbar_h;
break;
case 4:// center default
x = ((sw - vbar_w) / 2) + x;
break;
case 5:// center higher
x = ((sw - vbar_w) / 2) + x;
y = sh - sh/15;
break;
}
icon_x = x + spacer;
icon_y = y + ((vbar_h - icon_h) / 2);
progress_x = icon_x + icon_w + spacer;
progress_y = y + ((vbar_h - progress_h) / 2);
if (paintDigits) {
digit_x = progress_x + progress_w + spacer/2;
digit_y = y + digit_h + digit_offset + ((vbar_h - digit_h) / 2);
digit_b_x = digit_x - spacer/4;
digit_b_w = vbar_w - (digit_b_x - x);
}
}
CVolume* CVolume::getInstance()
{
static CVolume* Volume = NULL;
if(!Volume)
Volume = new CVolume();
return Volume;
}
void CVolume::AudioMute(int newValue, bool isEvent)
{
if((g_settings.current_volume == 0) && (g_settings.show_mute_icon == 1))
return;
CNeutrinoApp* neutrino = CNeutrinoApp::getInstance();
bool doInit = newValue != (int) neutrino->isMuted();
CVFD::getInstance()->setMuted(newValue);
neutrino->setCurrentMuted(newValue);
g_Zapit->muteAudio(newValue);
if( isEvent && ( neutrino->getMode() != CNeutrinoApp::mode_scart ) && ( neutrino->getMode() != CNeutrinoApp::mode_audio) && ( neutrino->getMode() != CNeutrinoApp::mode_pic))
{
if ((mute_ay_old != mute_ay) && (mute_ay_old > 0))
frameBuffer->paintBackgroundBoxRel(mute_ax, mute_ay_old, mute_dx, mute_dy);
if ((g_settings.mode_clock) && (doInit))
CInfoClock::getInstance(true)->ClearDisplay();
frameBuffer->paintMuteIcon(newValue, mute_ax, mute_ay, mute_dx, mute_dy, MuteIconFrame);
if (doInit) {
Init();
CInfoClock::getInstance(true)->Init(true);
}
}
}
void CVolume::setvol(int vol)
{
audioDecoder->setVolume(vol, vol);
}
void CVolume::setVolume(const neutrino_msg_t key, const bool bDoPaint, bool nowait)
{
neutrino_msg_t msg = key;
int vol = g_settings.current_volume;
fb_pixel_t * pixbuf = NULL;
if(bDoPaint) {
pixbuf = new fb_pixel_t[(vbar_w+ShadowOffset) * (vbar_h+ShadowOffset)];
if(pixbuf!= NULL)
frameBuffer->SaveScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf);
// volumebar shadow
if (paintShadow)
frameBuffer->paintBoxRel(x+ShadowOffset , y+ShadowOffset , (paintDigits) ? vbar_w - vbar_h : vbar_w, vbar_h, colShadow, ROUNDED, CORNER_TOP_LEFT | CORNER_BOTTOM_LEFT);
// volumebar
frameBuffer->paintBoxRel(x , y , (paintDigits) ? vbar_w - vbar_h : vbar_w, vbar_h, colBar, ROUNDED, CORNER_TOP_LEFT | CORNER_BOTTOM_LEFT);
// frame for progress
frameBuffer->paintBoxRel(progress_x-pB, progress_y-pB, progress_w+pB*1, progress_h+pB*2, colFrame);
// volume icon
frameBuffer->paintIcon(NEUTRINO_ICON_VOLUME, icon_x, icon_y, 0, colBar);
g_volscale->reset();
refreshVolumebar(vol);
}
neutrino_msg_data_t data;
uint64_t timeoutEnd;
do {
if (msg <= CRCInput::RC_MaxRC)
{
int sub_chan_keybind = 0;
if (g_settings.mode_left_right_key_tv == SNeutrinoSettings::VOLUME && v_RemoteControl->subChannels.size() < 1)
sub_chan_keybind = 1;
if ((msg == CRCInput::RC_plus) || (sub_chan_keybind == 1 && (msg == CRCInput::RC_right))) {
if (g_settings.current_volume < 100 - g_settings.current_volume_step)
g_settings.current_volume += g_settings.current_volume_step;
else
g_settings.current_volume = 100;
if(CNeutrinoApp::getInstance()->isMuted()) {
if ((bDoPaint) && (pixbuf!= NULL)) {
frameBuffer->RestoreScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf);
delete [] pixbuf;
}
AudioMute(false, true);
Init();
setVolume(msg);
return;
}
}
else if ((msg == CRCInput::RC_minus) || (sub_chan_keybind == 1 && (msg == CRCInput::RC_left))) {
if (g_settings.current_volume > g_settings.current_volume_step)
g_settings.current_volume -= g_settings.current_volume_step;
else if ((g_settings.show_mute_icon == 1) && (g_settings.current_volume = 1)) {
(g_settings.current_volume = 1);
AudioMute( true, true);
g_settings.current_volume = 0;
}
else if (g_settings.show_mute_icon == 0)
g_settings.current_volume = 0;
}
else if (msg == CRCInput::RC_home)
break;
else {
g_RCInput->postMsg(msg, data);
break;
}
setvol(g_settings.current_volume);
timeoutEnd = CRCInput::calcTimeoutEnd(nowait ? 1 : 3);
}
else if (msg == NeutrinoMessages::EVT_VOLCHANGED) {
timeoutEnd = CRCInput::calcTimeoutEnd(3);
}
else if (CNeutrinoApp::getInstance()->handleMsg(msg, data) & messages_return::unhandled) {
g_RCInput->postMsg(msg, data);
break;
}
if (bDoPaint) {
if(vol != g_settings.current_volume) {
vol = g_settings.current_volume;
refreshVolumebar(g_settings.current_volume);
}
}
CVFD::getInstance()->showVolume(g_settings.current_volume);
if (msg != CRCInput::RC_timeout) {
g_RCInput->getMsgAbsoluteTimeout(&msg, &data, &timeoutEnd, true );
}
} while (msg != CRCInput::RC_timeout);
if( (bDoPaint) && (pixbuf!= NULL) ) {
frameBuffer->RestoreScreen(x, y, vbar_w+ShadowOffset, vbar_h+ShadowOffset, pixbuf);
delete [] pixbuf;
}
}
void CVolume::refreshVolumebar(int current_volume)
{
// progressbar
g_volscale->paintProgressBar2(progress_x, progress_y, current_volume);
if (paintDigits) {
// shadow for erase digits
if (paintShadow)
frameBuffer->paintBoxRel(digit_b_x+ShadowOffset, y+ShadowOffset, digit_b_w, vbar_h, colShadow, ROUNDED, CORNER_TOP_RIGHT | CORNER_BOTTOM_RIGHT);
// erase digits
frameBuffer->paintBoxRel(digit_b_x, y, digit_b_w, vbar_h, colBar, ROUNDED, CORNER_TOP_RIGHT | CORNER_BOTTOM_RIGHT);
// digits
char buff[4];
snprintf(buff, 4, "%3d", current_volume);
g_Font[VolumeFont]->RenderString(digit_x, digit_y, digit_w, buff, colContent);
}
}

65
src/driver/volume.h Normal file
View File

@@ -0,0 +1,65 @@
/*
volume bar - Neutrino-GUI
Copyright (C) 2001 Steffen Hehn 'McClean'
and some other guys
Homepage: http://dbox.cyberphoria.org/
Copyright (C) 2011-2012 M. Liebmann (micha-bbg)
License: GPL
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef __CVOLUME__
#define __CVOLUME__
#define ROUNDED g_settings.rounded_corners ? vbar_h/2 : 0
class CVolume
{
private:
void refreshVolumebar(int current_volume);
int x, y, sy, sw, sh;
int mute_ax, mute_ay, mute_dy, mute_ay_old;
int mute_icon_dx, mute_icon_dy;
int icon_w, icon_h, icon_x, icon_y;
int vbar_w, vbar_h;
int progress_w, progress_h, progress_x, progress_y, pB;
int digit_w, digit_h, digit_offset, digit_x, digit_y, digit_b_x, digit_b_w;
int VolumeFont, colShadow, colBar, colFrame, colContent;
int ShadowOffset;
int rounded;
bool paintShadow, paintDigits, MuteIconFrame;
public:
CVolume();
~CVolume();
static CVolume* getInstance();
int spacer, mute_dx;
void Init();
void AudioMute(int newValue, bool isEvent= false);
void setvol(int vol);
void setVolume(const neutrino_msg_t key, const bool bDoPaint = true, bool nowait = false);
int getStartPosTop(){ return sy; }
int getEndPosRight(){ return sw; }
};
#endif // __CVOLUME__