summaryrefslogtreecommitdiffabout
path: root/gammu/emb/common/service/gsmring.c
Side-by-side diff
Diffstat (limited to 'gammu/emb/common/service/gsmring.c') (more/less context) (show whitespace changes)
-rw-r--r--gammu/emb/common/service/gsmring.c45
1 files changed, 43 insertions, 2 deletions
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
index 7df46f1..dab028c 100644
--- a/gammu/emb/common/service/gsmring.c
+++ b/gammu/emb/common/service/gsmring.c
@@ -1,33 +1,36 @@
/* (c) 2001-2004 by Marcin Wiacek */
-/* Based on some work from Ralf Thelen (7110 ringtones),
- * Gnokii (RTTL and SM) and others
+/* Based on some work from Ralf Thelen (7110 ringtones) and others */
+/* Based on some work (RTTL and SM) from Gnokii (www.gnokii.org)
+ * (C) 1999-2000 Hugh Blemings & Pavel Janik ml. (C) 2001-2004 Pawel Kot
+ * GNU GPL version 2 or later
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
+#include <sys/stat.h>
#ifdef WIN32
# include <windows.h>
#endif
#include "../gsmcomon.h"
#include "../misc/coding/coding.h"
#include "../gsmstate.h"
#include "gsmring.h"
#include "sms/gsmsms.h"
int GSM_RingNoteGetFrequency(GSM_RingNote Note)
{
double freq=0;
/* Values according to the software from http://iki.fi/too/sw/xring/
* generated with:
* perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
*/
switch (Note.Note) {
case Note_C : freq = 523.3; break;
case Note_Cis: freq = 554.4; break;
case Note_D : freq = 587.3; break;
case Note_Dis: freq = 622.3; break;
case Note_E : freq = 659.3; break;
@@ -135,48 +138,54 @@ GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
return ERR_NONE;
}
static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
{
char nullchar=0x00;
fwrite(&nullchar,1,1,file);
fwrite(&nullchar,1,1,file);
fprintf(file,"\x0C\x01\x2C");
fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
fwrite(&nullchar,1,1,file);
fwrite(&nullchar,1,1,file);
fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
return ERR_NONE;
}
static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
{
fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
return ERR_NONE;
}
+static GSM_Error savemmf(FILE *file, GSM_Ringtone *ringtone)
+{
+ fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
+ return ERR_NONE;
+}
+
GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
{
GSM_RingNoteScale DefNoteScale;
GSM_RingNoteDuration DefNoteDuration;
GSM_RingNoteStyle DefNoteStyle=0;
int DefNoteTempo=0;
bool started = false, firstcomma = true;
GSM_RingNote *Note;
unsigned char buffer[15];
int i,j,k=0;
/* Saves ringtone name */
fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
/* Find the most frequently used duration */
for (i=0;i<6;i++) buffer[i]=0;
for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
Note = &ringtone->NoteTone.Commands[i].Note;
/* some durations need 2 bytes in file, some 1 */
if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
@@ -464,48 +473,51 @@ GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
if (strstr(FileName,".ott")) {
saveott(file,ringtone);
#ifndef ENABLE_LGPL
} else if (strstr(FileName,".mid")) {
savemid(file,ringtone);
#endif
} else if (strstr(FileName,".rng")) {
saveott(file,ringtone);
} else if (strstr(FileName,".imy")) {
saveimelody(file,ringtone);
} else if (strstr(FileName,".ime")) {
saveimelody(file,ringtone);
} else if (strstr(FileName,".wav")) {
savewav(file,ringtone);
} else {
saverttl(file, ringtone);
}
break;
case RING_NOKIABINARY:
savebin(file, ringtone);
break;
case RING_MIDI:
savepuremidi(file, ringtone);
break;
+ case RING_MMF:
+ savemmf(file, ringtone);
+ break;
}
fclose(file);
return ERR_NONE;
}
static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
{
GSM_RingNoteScale DefNoteScale = Scale_880;
GSM_RingNoteDuration DefNoteDuration = Duration_1_4;
GSM_RingNoteStyle DefNoteStyle = NaturalStyle;
int DefNoteTempo = 63, i=0;
unsigned char buffer[2000],Name[100];
GSM_RingNote *Note;
fread(buffer, 2000, 1, file);
ringtone->NoteTone.NrCommands = 0;
/* -------------- name ---------------- */
while (buffer[i] != ':') {
if (buffer[i] == 0x00) return ERR_NONE;
@@ -748,121 +760,150 @@ static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
i=5;
while (buffer[i]!=0x00) i++;
EncodeUnicode(ringtone->Name,buffer+5,i-5);
while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
i++;
}
ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
{
unsigned char buffer[30000];
dbgprintf("loading midi\n");
EncodeUnicode(ringtone->Name,"MIDI",4);
ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
+static GSM_Error loadmmf(FILE *file, GSM_Ringtone *ringtone)
+{
+ struct stat st;
+ char *buffer;
+ int length;
+
+ dbgprintf("loading smaf file\n");
+ fstat(fileno(file), &st);
+ ringtone->BinaryTone.Length = length = st.st_size;
+ ringtone->BinaryTone.Buffer = buffer = malloc(length);
+ if (buffer == NULL)
+ return ERR_MOREMEMORY;
+ fread(buffer, 1, length, file);
+
+ dbgprintf("Length %i name \"%s\"\n", length,
+ DecodeUnicodeString(ringtone->Name));
+
+ return ERR_NONE;
+}
+
static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
{
unsigned char buffer[2000];
ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
if (buffer[18]==0x00 && buffer[21]!=0x02) {
/* DCT3, Unicode subformat, 62xx & 7110 */
CopyUnicodeString(ringtone->Name,buffer+18);
ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
} else {
/* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
}
dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
return ERR_NONE;
}
GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
{
FILE *file;
unsigned char buffer[300];
GSM_Error error = ERR_UNKNOWN;
dbgprintf("Loading ringtone %s\n",FileName);
file = fopen(FileName, "rb");
if (file == NULL) return ERR_CANTOPENFILE;
/* Read the header of the file. */
fread(buffer, 1, 4, file);
if (ringtone->Format == 0x00) {
ringtone->Format = RING_NOTETONE;
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x0C && buffer[3]==0x01) {
ringtone->Format = RING_NOKIABINARY;
}
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x00) {
ringtone->Format = RING_NOKIABINARY;
}
if (buffer[0]==0x4D && buffer[1]==0x54 &&
buffer[2]==0x68 && buffer[3]==0x64) {
ringtone->Format = RING_MIDI;
}
+ if (buffer[0]==0x4D && buffer[1]==0x4D &&
+ buffer[2]==0x4D && buffer[3]==0x44) {
+ ringtone->Format = RING_MMF;
+ }
}
rewind(file);
switch (ringtone->Format) {
case RING_NOTETONE:
if (buffer[0]==0x02 && buffer[1]==0x4A) {
error=loadott(file,ringtone);
} else if (buffer[0]==0xC7 && buffer[1]==0x45) {
error=loadcommunicator(file,ringtone);
} else {
error=loadrttl(file,ringtone);
}
ringtone->NoteTone.AllNotesScale=false;
break;
case RING_NOKIABINARY:
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x0C && buffer[3]==0x01) {
error=loadbin(file,ringtone);
}
if (buffer[0]==0x00 && buffer[1]==0x00 &&
buffer[2]==0x00) {
error=loadre(file,ringtone);
}
break;
case RING_MIDI:
EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
error = loadpuremidi(file,ringtone);
+ break;
+ case RING_MMF:
+ EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
+ error = loadmmf(file,ringtone);
+ break;
}
fclose(file);
return(error);
}
/* -------------------------- required with Nokia & RTTL ------------------- */
/* Beats per Minute like written in Smart Messaging */
static int SM_BeatsPerMinute[] = {
25, 28, 31, 35, 40, 45, 50, 56, 63, 70,
80, 90, 100, 112, 125, 140, 160, 180, 200, 225,
250, 285, 320, 355, 400, 450, 500, 565, 635, 715,
800, 900
};
int GSM_RTTLGetTempo(int Beats)
{
int i=0;
while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
return i<<3;
}