Mozilla/mozilla/mailnews/base/src/nsSoundDatasource.cpp
gerv%gerv.net b759f30f5f Bug 331921 - Fix up some corrupt/dodgy Initial Developer lines.
git-svn-id: svn://10.0.0.236/trunk@193253 18797224-902f-48f8-a5cc-f745e15eee43
2006-03-30 07:57:05 +00:00

594 lines
17 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsSoundDatasource.h"
#include "nsIRDFService.h"
#include "nsRDFCID.h"
#include "nsIComponentManager.h"
#include "nsXPIDLString.h"
#include "rdf.h"
#include "nsIServiceManager.h"
#include "nsEnumeratorUtils.h"
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsCRT.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIFileURL.h"
#include "nsISimpleEnumerator.h"
#include "nsNetCID.h"
#include "nsIFile.h"
#include "nsILocalFile.h"
#define SOUND_ROOT "moz-mailsounds://"
#define DEFAULT_SOUND_URL "_moz_mailbeep"
#define DEFAULT_SOUND_URL_NAME "System New Mail Sound" // move to string bundle
#define PREF_NEW_MAIL_URL "mail.biff.play_sound.url"
#define WAV_EXTENSION ".wav"
#define WAV_EXTENSION_LENGTH 4
#define FILE_SCHEME "file://"
#define FILE_SCHEME_LEN 7
#ifdef XP_WIN
#include <windows.h>
#endif
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
nsSoundDatasource::nsSoundDatasource()
{
}
nsSoundDatasource::~nsSoundDatasource()
{
}
NS_IMPL_ISUPPORTS1(nsSoundDatasource, nsIRDFDataSource)
nsresult
nsSoundDatasource::Init()
{
nsresult rv;
mRDFService = do_GetService(kRDFServiceCID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
getter_AddRefs(kNC_Child));
NS_ENSURE_SUCCESS(rv,rv);
rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
getter_AddRefs(kNC_Name));
NS_ENSURE_SUCCESS(rv,rv);
rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "SoundURL"),
getter_AddRefs(kNC_SoundURL));
NS_ENSURE_SUCCESS(rv,rv);
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::GetURI(char **aURI)
{
if ((*aURI = nsCRT::strdup("rdf:mailsounds")) == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
else
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::GetSource(nsIRDFResource *property, nsIRDFNode *target, PRBool tv, nsIRDFResource **source)
{
NS_ENSURE_ARG_POINTER(property);
NS_ENSURE_ARG_POINTER(target);
NS_ENSURE_ARG_POINTER(source);
*source = nsnull;
return NS_RDF_NO_VALUE;
}
NS_IMETHODIMP
nsSoundDatasource::GetTarget(nsIRDFResource *source,
nsIRDFResource *property,
PRBool tv,
nsIRDFNode **target /* out */)
{
nsresult rv = NS_RDF_NO_VALUE;
NS_ENSURE_ARG_POINTER(property);
NS_ENSURE_ARG_POINTER(target);
NS_ENSURE_ARG_POINTER(source);
*target = nsnull;
// we only have positive assertions in the sound data source.
if (!tv)
return NS_RDF_NO_VALUE;
nsXPIDLCString value;
rv = source->GetValue(getter_Copies(value));
NS_ENSURE_SUCCESS(rv,rv);
if (property == kNC_Name.get()) {
nsCOMPtr<nsIRDFLiteral> name;
if (strcmp(value.get(), DEFAULT_SOUND_URL)) {
const char *lastSlash = strrchr(value.get(), '/');
// turn "file://C|/winnt/media/foo.wav" into "foo".
nsCAutoString soundName(lastSlash + 1);
soundName.Truncate(soundName.Length() - WAV_EXTENSION_LENGTH);
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(soundName).get(), getter_AddRefs(name));
}
else {
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(DEFAULT_SOUND_URL_NAME).get(), getter_AddRefs(name));
}
NS_ENSURE_SUCCESS(rv,rv);
if (!name)
return NS_RDF_NO_VALUE;
else
return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
}
else if (property == kNC_SoundURL.get()) {
nsCOMPtr<nsIRDFLiteral> name;
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(value).get(), getter_AddRefs(name));
NS_ENSURE_SUCCESS(rv,rv);
if (!name)
return NS_RDF_NO_VALUE;
else
return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
}
else if (property == kNC_Child.get()) {
if (strcmp(value.get(),SOUND_ROOT) == 0) {
nsCOMPtr <nsIRDFResource> childResource;
rv = mRDFService->GetResource(NS_LITERAL_CSTRING(DEFAULT_SOUND_URL),
getter_AddRefs(childResource));
NS_ENSURE_SUCCESS(rv,rv);
return childResource->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
}
else {
return NS_RDF_NO_VALUE;
}
}
else {
// do nothing
}
return(NS_RDF_NO_VALUE);
}
#ifdef XP_WIN
BYTE * GetValueBytes( HKEY hKey, const char *pValueName)
{
LONG err;
DWORD bufSz;
LPBYTE pBytes = NULL;
err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, NULL, &bufSz);
if (err == ERROR_SUCCESS) {
pBytes = new BYTE[bufSz];
err = ::RegQueryValueEx( hKey, pValueName, NULL, NULL, pBytes, &bufSz);
if (err != ERROR_SUCCESS) {
delete [] pBytes;
pBytes = NULL;
}
}
return( pBytes);
}
#endif
NS_IMETHODIMP
nsSoundDatasource::GetTargets(nsIRDFResource *source,
nsIRDFResource *property,
PRBool tv,
nsISimpleEnumerator **targets /* out */)
{
nsresult rv = NS_OK;
NS_ENSURE_ARG_POINTER(property);
NS_ENSURE_ARG_POINTER(targets);
NS_ENSURE_ARG_POINTER(source);
*targets = nsnull;
// we only have positive assertions in the sound data source.
if (!tv)
return NS_RDF_NO_VALUE;
nsXPIDLCString value;
rv = source->GetValue(getter_Copies(value));
NS_ENSURE_SUCCESS(rv,rv);
if (property == kNC_Child.get()) {
if (strcmp(value.get(), SOUND_ROOT))
return NS_NewEmptyEnumerator(targets);
nsCOMPtr<nsISupportsArray> children;
rv = NS_NewISupportsArray(getter_AddRefs(children));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsIRDFResource> res;
rv = mRDFService->GetResource(NS_LITERAL_CSTRING(DEFAULT_SOUND_URL), getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv,rv);
rv = children->AppendElement(res);
NS_ENSURE_SUCCESS(rv,rv);
#ifdef XP_WIN
nsCAutoString soundFolder;
HKEY sKey;
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", 0, KEY_QUERY_VALUE, &sKey) == ERROR_SUCCESS) {
BYTE *pBytes = GetValueBytes( sKey, "MediaPath");
if (pBytes) {
soundFolder = (const char *)pBytes;
delete [] pBytes;
}
::RegCloseKey( sKey);
}
nsCOMPtr <nsILocalFile> directory = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = directory->InitWithPath(NS_ConvertASCIItoUTF16(soundFolder));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsISimpleEnumerator> dirEntries;
rv = directory->GetDirectoryEntries(getter_AddRefs(dirEntries));
NS_ENSURE_SUCCESS(rv,rv);
if (dirEntries) {
PRBool hasMore = PR_FALSE;
PRInt32 dirCount = 0, fileCount = 0;
while (NS_SUCCEEDED(dirEntries->HasMoreElements(&hasMore)) && hasMore) {
nsCOMPtr <nsISupports> nextItem;
dirEntries->GetNext(getter_AddRefs(nextItem));
nsCOMPtr <nsIFile> theFile = do_QueryInterface(nextItem);
PRBool isDirectory;
theFile->IsDirectory(&isDirectory);
if (!isDirectory) {
nsCOMPtr<nsIFileURL> theFileURL = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
rv = theFileURL->SetFile(theFile);
NS_ENSURE_SUCCESS(rv,rv);
nsXPIDLCString theFileSpec;
rv = theFileURL->GetSpec(theFileSpec);
NS_ENSURE_SUCCESS(rv,rv);
// if it doesn't end with .wav, or it contains a %20, skip it.
if (!strstr(theFileSpec.get(),"%20") && (theFileSpec.Length() > WAV_EXTENSION_LENGTH)) {
if (strcmp(theFileSpec.get() + theFileSpec.Length() - WAV_EXTENSION_LENGTH, WAV_EXTENSION) == 0) {
rv = mRDFService->GetResource(theFileSpec, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv,rv);
rv = children->AppendElement(res);
NS_ENSURE_SUCCESS(rv,rv);
}
}
}
}
}
#endif
// add entry for the pref specified one, if a file:// url
// if not, it's a system sound, and we already added it.
nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
nsXPIDLCString soundURLSpec;
rv = prefBranch->GetCharPref(PREF_NEW_MAIL_URL,getter_Copies(soundURLSpec));
NS_ENSURE_SUCCESS(rv,rv);
if (!strncmp(soundURLSpec.get(), FILE_SCHEME, FILE_SCHEME_LEN)) {
rv = mRDFService->GetResource(soundURLSpec, getter_AddRefs(res));
NS_ENSURE_SUCCESS(rv,rv);
rv = children->AppendElement(res);
NS_ENSURE_SUCCESS(rv,rv);
}
nsISimpleEnumerator* result = new nsArrayEnumerator(children);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*targets = result);
return NS_OK;
}
else if (property == kNC_SoundURL.get()) {
nsCOMPtr<nsIRDFLiteral> name;
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(value).get(), getter_AddRefs(name));
NS_ENSURE_SUCCESS(rv,rv);
nsISimpleEnumerator* result = new nsSingletonEnumerator(name);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*targets = result);
return NS_OK;
}
else if (property == kNC_Name.get()) {
nsCOMPtr<nsIRDFLiteral> name;
if (strcmp(value.get(), DEFAULT_SOUND_URL)) {
const char *lastSlash = strrchr(value.get(), '/');
// turn "file://C|/winnt/media/foo.wav" into "foo".
nsCAutoString soundName(lastSlash + 1);
soundName.Truncate(soundName.Length() - WAV_EXTENSION_LENGTH);
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(soundName).get(), getter_AddRefs(name));
}
else {
rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(DEFAULT_SOUND_URL_NAME).get(), getter_AddRefs(name));
}
NS_ENSURE_SUCCESS(rv,rv);
nsISimpleEnumerator* result = new nsSingletonEnumerator(name);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*targets = result);
return NS_OK;
}
else {
// do nothing
}
return NS_NewEmptyEnumerator(targets);
}
NS_IMETHODIMP
nsSoundDatasource::Assert(nsIRDFResource *source,
nsIRDFResource *property,
nsIRDFNode *target,
PRBool tv)
{
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHODIMP
nsSoundDatasource::Unassert(nsIRDFResource *source,
nsIRDFResource *property,
nsIRDFNode *target)
{
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHODIMP
nsSoundDatasource::Change(nsIRDFResource* aSource,
nsIRDFResource* aProperty,
nsIRDFNode* aOldTarget,
nsIRDFNode* aNewTarget)
{
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHODIMP
nsSoundDatasource::Move(nsIRDFResource* aOldSource,
nsIRDFResource* aNewSource,
nsIRDFResource* aProperty,
nsIRDFNode* aTarget)
{
return NS_RDF_ASSERTION_REJECTED;
}
NS_IMETHODIMP
nsSoundDatasource::HasAssertion(nsIRDFResource *source,
nsIRDFResource *property,
nsIRDFNode *target,
PRBool tv,
PRBool *hasAssertion /* out */)
{
NS_ENSURE_ARG_POINTER(property);
NS_ENSURE_ARG_POINTER(target);
NS_ENSURE_ARG_POINTER(source);
NS_ENSURE_ARG_POINTER(hasAssertion);
*hasAssertion = PR_FALSE;
// we only have positive assertions in the sound data source.
if (!tv)
return NS_OK;
if (property == kNC_Child.get()) {
nsXPIDLCString value;
nsresult rv = source->GetValue(getter_Copies(value));
NS_ENSURE_SUCCESS(rv,rv);
// only root has children
*hasAssertion = (strcmp(value.get(), SOUND_ROOT) == 0);
return NS_OK;
}
else if (property == kNC_Name.get() || property == kNC_SoundURL.get()) {
// everything has a name and a url
*hasAssertion = PR_TRUE;
}
else {
// do nothing
}
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSoundDatasource::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, PRBool *result)
{
nsresult rv = NS_OK;
if (aArc == kNC_Child.get()) {
nsXPIDLCString value;
rv = source->GetValue(getter_Copies(value));
// only root has children
*result = (strcmp(value.get(), SOUND_ROOT) == 0);
return NS_OK;
}
else if (aArc == kNC_Name.get() || aArc == kNC_SoundURL.get()) {
*result = PR_TRUE;
return NS_OK;
}
*result = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::ArcLabelsIn(nsIRDFNode *node,
nsISimpleEnumerator ** labels /* out */)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSoundDatasource::ArcLabelsOut(nsIRDFResource *source,
nsISimpleEnumerator **labels /* out */)
{
NS_ENSURE_ARG_POINTER(labels);
NS_ENSURE_ARG_POINTER(source);
nsresult rv = NS_OK;
//return NS_NewEmptyEnumerator(labels);
nsCOMPtr<nsISupportsArray> array;
rv = NS_NewISupportsArray(getter_AddRefs(array));
NS_ENSURE_SUCCESS(rv,rv);
array->AppendElement(kNC_Name);
array->AppendElement(kNC_SoundURL);
nsXPIDLCString value;
rv = source->GetValue(getter_Copies(value));
// only root has children
PRBool hasChildren = (strcmp(value.get(), SOUND_ROOT) == 0);
if (hasChildren) {
array->AppendElement(kNC_Child);
}
nsISimpleEnumerator* result = new nsArrayEnumerator(array);
if (!result)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(result);
*labels = result;
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::GetAllResources(nsISimpleEnumerator** aCursor)
{
NS_NOTYETIMPLEMENTED("sorry!");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSoundDatasource::GetAllCmds(nsIRDFResource* source,
nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
{
return(NS_NewEmptyEnumerator(commands));
}
NS_IMETHODIMP
nsSoundDatasource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
nsIRDFResource* aCommand,
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
PRBool* aResult)
{
return(NS_ERROR_NOT_IMPLEMENTED);
}
NS_IMETHODIMP
nsSoundDatasource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
nsIRDFResource* aCommand,
nsISupportsArray/*<nsIRDFResource>*/* aArguments)
{
return(NS_ERROR_NOT_IMPLEMENTED);
}
NS_IMETHODIMP
nsSoundDatasource::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, PRBool aTruthValue, nsISimpleEnumerator **_retval)
{
NS_ASSERTION(PR_FALSE, "Not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
nsSoundDatasource::AddObserver(nsIRDFObserver *n)
{
NS_ENSURE_ARG_POINTER(n);
if (!mObservers)
{
nsresult rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
if (NS_FAILED(rv)) return rv;
}
mObservers->AppendElement(n);
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::RemoveObserver(nsIRDFObserver *n)
{
NS_ENSURE_ARG_POINTER(n);
if (!mObservers)
return NS_OK;
mObservers->RemoveElement(n);
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::BeginUpdateBatch()
{
return NS_OK;
}
NS_IMETHODIMP
nsSoundDatasource::EndUpdateBatch()
{
return NS_OK;
}