mediarecorder.cpp

来自「Trolltech公司发布的图形界面操作系统。可在qt-embedded-2.3」· C++ 代码 · 共 1,099 行 · 第 1/3 页

CPP
1,099
字号
/************************************************************************ Copyright (C) 2000-2005 Trolltech AS.  All rights reserved.**** This file is part of the Qtopia Environment.** ** This program is free software; you can redistribute it and/or modify it** under the terms of the GNU General Public License as published by the** Free Software Foundation; either version 2 of the License, or (at your** option) any later version.** ** A copy of the GNU GPL license version 2 is included in this package as ** LICENSE.GPL.**** This program 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 General Public License for more details.**** In addition, as a special exception Trolltech gives permission to link** the code of this program with Qtopia applications copyrighted, developed** and distributed by Trolltech under the terms of the Qtopia Personal Use** License Agreement. You must comply with the GNU General Public License** in all respects for all of the code used other than the applications** licensed under the Qtopia Personal Use License Agreement. If you modify** this file, you may extend this exception to your version of the file,** but you are not obligated to do so. If you do not wish to do so, delete** this exception statement from your version.** ** See http://www.trolltech.com/gpl/ for GPL licensing information.**** Contact info@trolltech.com if any conditions of this licensing are** not clear to you.************************************************************************/#define	QTOPIA_INTERNAL_MIMEEXT#include "mediarecorder.h"#include "mediarecorderbase.h"#include "audioinput.h"#include "audiodevice.h"#include "samplebuffer.h"#include "pluginlist.h"#include "timeprogressbar.h"#include "confrecorder.h"#include "waveform.h"#include <qtopia/global.h>#include <qtopia/fileselector.h>#include <qtopia/applnk.h>#include <qtopia/resource.h>#include <qtopia/config.h>#include <qtopia/storage.h>#include <qtopia/locationcombo.h>#include <qtopia/qpeapplication.h>#include <qtopia/qpemenubar.h>#include <qtopia/qpetoolbar.h>#include <qtopia/mimetype.h>#include <qtopia/fileselector.h>#include <qtopia/categories.h>#ifdef Q_WS_QWS#include <qtopia/qcopenvelope_qws.h>#endif#include <qaction.h>#include <qbuttongroup.h>#include <qcombobox.h>#include <qmessagebox.h>#include <qfile.h>#ifdef QTOPIA_PHONE#include <qtopia/contextmenu.h>#include <qtopia/contextbar.h>#endif#include <stdlib.h>MediaRecorder::MediaRecorder( QWidget *parent, const char *name, WFlags f )    : QMainWindow( parent, name, f ){    audioDeviceIsReady = false;    startWhenAudioDeviceReady = false;    requestMode = false;    // Load the media plugins.    recorderPlugins = new MediaRecorderPluginList();    playerPlugins = new MediaPlayerPluginList();    setToolBarsMovable( FALSE );    setBackgroundMode( PaletteButton );    setCaption( tr("Voice Notes") );    setIcon( Resource::loadPixmap( "SoundPlayer" ) );    // We don't need an input method with this application.    QPEApplication::setInputMethodHint( this, QPEApplication::AlwaysOff );    // Make sure that the "Recordings" category is registered.    Categories cats;    cats.load(categoryFileName());    recordingsCategory = cats.id("Document View","_Recordings"); // No tr    if ( !recordingsCategory ) {	recordingsCategory =	    cats.addCategory("Document View","_Recordings"); // No tr	cats.save(categoryFileName());    }    stack = new QWidgetStack( this );    stack->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );    setCentralWidget( stack );    contents = new MediaRecorderBase( stack );    stack->addWidget( contents, 0 );    selector = new FileSelector( "audio/*", stack, "fileselector", TRUE, FALSE );    selector->setCurrentCategory( recordingsCategory );    selector->setSortMode( FileSelector::ReverseChronological );    stack->addWidget( selector, 1 );    connect( selector, SIGNAL(fileSelected(const DocLnk&)),	     this, SLOT(fileSelected(const DocLnk&)) );    connect( selector, SIGNAL(newSelected(const DocLnk&)),	     this, SLOT(newSelected(const DocLnk&)) );#ifdef QTOPIA_PHONE    // Create the context menu for the file selector screen.    ContextMenu *options = new ContextMenu( selector );    selector->addOptions( options );    // Create the context menu for the record/playback screen.    options = new ContextMenu( contents );#else    QPEToolBar *bar = new QPEToolBar( this );    bar->setHorizontalStretchable( TRUE );    menu = bar;    QPEMenuBar *mb = new QPEMenuBar( bar );    QPopupMenu *options = new QPopupMenu( this );    mb->insertItem( tr( "Options" ), options );#endif    configureAction = new QAction(tr( "Settings..."), Resource::loadIconSet("settings"), QString::null, 0, this, 0 );    connect( configureAction, SIGNAL( activated() ), this, SLOT( configure() ) );    configureAction->setWhatsThis( tr("Configure the recording quality settings.") );    configureAction->addTo( options );    configureAction->setEnabled( TRUE );    initializeContents();    switchToFileSelector();    audioInput = 0;    audioOutput = 0;#ifdef RECORD_THEN_SAVE    samples = 0;#endif    sampleBuffer = 0;    recordTime = 0;    recording = FALSE;    playing = FALSE;    io = 0;    recordLightState = FALSE;    lightTimer = new QTimer( this );    // Hook up interesting signals.    connect( contents->recordButton, SIGNAL( clicked() ),	     this, SLOT( recordClicked() ) );    connect( contents->replayButton, SIGNAL( clicked() ),	     this, SLOT( replayClicked() ) );    connect( contents->deleteButton, SIGNAL( clicked() ),	     this, SLOT( deleteClicked() ) );    connect( lightTimer, SIGNAL( timeout() ),	     this, SLOT( recordLightBlink() ) );#ifdef QTOPIA_PHONE    // Don't display the buttons in Qtopia Phone Edition, because    // they take up too much screen real estate and have confusing    // key navigation behaviours.    //contents->recordButton->hide();    contents->replayButton->hide();    contents->deleteButton->hide();    // Make the context key say "Record".    setContextKey( TRUE );#endif    // Listen on the system tray for clicks on the record light so that    // we can raise the application when the user clicks on it.    trayChannel = new QCopChannel( "Qt/Tray", this );    connect( trayChannel, SIGNAL(received(const QCString&,const QByteArray&)),	     this, SLOT(traySocket(const QCString&,const QByteArray&)) );    // Listen for app messages, particularly the "recordSound" request.    connect( qApp, SIGNAL(appMessage(const QCString&,const QByteArray&)),             this, SLOT(appMessage(const QCString&,const QByteArray&)) );    // Force the MIME type handling system to preload the list    // of extensions.  If we don't do this, then "startRecording"    // ends up being _very_ slow.    MimeType type("audio/x-wav");}MediaRecorder::~MediaRecorder(){    delete recorderPlugins;    delete playerPlugins;    if ( audioInput )	delete audioInput;    if ( audioOutput )	delete audioOutput;#ifdef RECORD_THEN_SAVE    if ( samples )	delete samples;#endif    if ( sampleBuffer )	delete[] sampleBuffer;    if ( io )	delete io;    if ( lightTimer )	delete lightTimer;}void MediaRecorder::initializeContents(){    // Set the waveform background to black.    contents->waveform->setBackgroundColor ( black );    // The progress bar initially has no time display.  This will be fixed    // up when we start recording.    contents->progress->setTotalSteps( 10 );    contents->progress->setProgress( -1 );    // Cannot replay yet, because there is no recorded sound.    setReplayEnabled( FALSE );    setDeleteEnabled( FALSE );    // Load the initial quality settings.    config = new ConfigureRecorder( qualities, recorderPlugins, this );    contents->qualityCombo->setCurrentItem(config->currentQuality());    setQualityDisplay( qualities[config->currentQuality()] );    connect( contents->qualityCombo, SIGNAL( activated(int) ),	     this, SLOT( qualityChanged(int) ) );    connect( contents->storageLocation, SIGNAL(newPath()), 	     this, SLOT(newLocation()) );    recomputeMaxTime();#ifdef QTOPIA_PHONE    // Disable the settings boxes in phone mode.    contents->GroupBox1->hide();    contents->GroupBox2->hide();#endif}void MediaRecorder::setQualityDisplay( const QualitySetting& quality ){    QString str;    QString format;    int index;    // Map the MIME type to a format name.  Do the best we can with    // the MIME type and tag if that is all we have.    index = recorderPlugins->indexFromType		( quality.mimeType, quality.formatTag );    if( index >= 0 ) {    	format = recorderPlugins->formatNameAt( (uint)index );    } else if( quality.mimeType.startsWith( "audio/" ) ) {    	format = quality.mimeType.mid(6) + " [" + quality.formatTag + "]";    } else {    	format = quality.mimeType + " [" + quality.formatTag + "]";    }    // Format the details and display them.    int khz = (quality.frequency / 1000);    if ( quality.channels == 1 ) {	str = tr("%1 kHz Mono - %2").arg(khz).arg(format);    } else {	str = tr("%1 kHz Stereo - %2").arg(khz).arg(format);    }    contents->details->setText( str );}void MediaRecorder::recomputeMaxTime(){    // Determine the maximum available space on the device.    const FileSystem *fs = contents->storageLocation->fileSystem();    long availBlocks;    long blockSize;    if ( fs ) {	availBlocks = fs->availBlocks();	blockSize = fs->blockSize();    } else {	availBlocks = 0;	blockSize = 512;    }    // Calculate the number of bytes per second for the current quality,    // by asking the plugin for an estimate.    MediaRecorderEncoder *encoder = recorderPlugins->fromType	    ( qualities[config->currentQuality()].mimeType,	      qualities[config->currentQuality()].formatTag );    long bytesPerSec;    if( encoder ) {    	bytesPerSec = encoder->estimateAudioBps	    ( qualities[config->currentQuality()].frequency,	      qualities[config->currentQuality()].channels,	      qualities[config->currentQuality()].formatTag );    	if ( bytesPerSec <= 0)	    bytesPerSec = 1;    } else {	// We don't have an encoder, so make an estimate based on	// assuming that the format is wav.    	bytesPerSec = qualities[config->currentQuality()].frequency *		      qualities[config->currentQuality()].channels * 2;    }    // Get an estimate of the maximum number of seconds that we can record.    // Use "double" to avoid truncation errors with 32-bit arithmetic.    long maxSecs = (long)(((double)availBlocks) * ((double)blockSize) /				(double)bytesPerSec);    // Truncate the maximum to a reasonable human-grokkable time boundary,    // as there is no point displaying things like "5 hrs 23 mins 6 secs".    if ( maxSecs >= (60 * 60 * 24) ) {	// Truncate to a 1 hour boundary.	maxSecs -= (maxSecs % (60 * 60));    } else if ( maxSecs >= (60 * 60 * 10) ) {	// Truncate to a 15 minute boundary.	maxSecs -= (maxSecs % (15 * 60));    } else if ( maxSecs >= (60 * 10) ) {	// Tuncate to a 1 minute boundary.	maxSecs -= (maxSecs % 60);    } else if ( maxSecs > 60 ) {	// Truncate to a 15 second boundary.	maxSecs -= (maxSecs % 15);    }    // Format the string for the max time field.    QString str;    if ( maxSecs >= (60 * 60 * 24) ) {	if ( (maxSecs % (60 * 60 * 24)) == 0 ) {	    str = tr("%1 days").arg((int)(maxSecs / (60 * 60 * 24)));	} else {	    str = tr("%1 days %2 hrs")		.arg((int)(maxSecs / (60 * 60 * 24)))		.arg((int)((maxSecs / (60 * 60)) % 24));	}    } else if ( maxSecs >= (60 * 60) ) {	if ( (maxSecs % (60 * 60)) == 0 ) {	    str = tr("%1 hrs").arg((int)(maxSecs / (60 * 60)));	} else {	    str = tr("%1 hrs %2 mins")		.arg((int)(maxSecs / (60 * 60)))		.arg((int)((maxSecs / 60) % 60));	}    } else if ( maxSecs >= 60 ) {	if ( (maxSecs % 60) == 0 ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?