summaryrefslogtreecommitdiffabout
path: root/gammu/emb
Unidiff
Diffstat (limited to 'gammu/emb') (more/less context) (ignore whitespace changes)
-rw-r--r--gammu/emb/common/common.pro1
-rw-r--r--gammu/emb/common/service/gsmring.c6
2 files changed, 6 insertions, 1 deletions
diff --git a/gammu/emb/common/common.pro b/gammu/emb/common/common.pro
index 9342cb7..0e719ee 100644
--- a/gammu/emb/common/common.pro
+++ b/gammu/emb/common/common.pro
@@ -1,186 +1,187 @@
1###################################################################### 1######################################################################
2# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004 2# Automatically generated by qmake (1.07a) Fri Jul 30 22:13:34 2004
3###################################################################### 3######################################################################
4 4
5TEMPLATE = lib 5TEMPLATE = lib
6DEPENDPATH += device \ 6DEPENDPATH += device \
7 misc \ 7 misc \
8 phone \ 8 phone \
9 protocol \ 9 protocol \
10 service \ 10 service \
11 device/bluetoth \ 11 device/bluetoth \
12 device/irda \ 12 device/irda \
13 device/serial \ 13 device/serial \
14 misc/coding \ 14 misc/coding \
15 phone/alcatel \ 15 phone/alcatel \
16 phone/at \ 16 phone/at \
17 phone/nokia \ 17 phone/nokia \
18 phone/obex \ 18 phone/obex \
19 phone/symbian \ 19 phone/symbian \
20 protocol/alcatel \ 20 protocol/alcatel \
21 protocol/at \ 21 protocol/at \
22 protocol/nokia \ 22 protocol/nokia \
23 protocol/obex \ 23 protocol/obex \
24 protocol/symbian \ 24 protocol/symbian \
25 service/backup \ 25 service/backup \
26 service/sms \ 26 service/sms \
27 phone/nokia/dct3 \ 27 phone/nokia/dct3 \
28 phone/nokia/dct4 28 phone/nokia/dct4
29INCLUDEPATH += . \ 29INCLUDEPATH += . \
30 misc/coding \ 30 misc/coding \
31 misc \ 31 misc \
32 device \ 32 device \
33 phone/nokia/dct4 \ 33 phone/nokia/dct4 \
34 phone/nokia/dct3 \ 34 phone/nokia/dct3 \
35 phone/at \ 35 phone/at \
36 phone/alcatel \ 36 phone/alcatel \
37 phone/obex \ 37 phone/obex \
38 phone/symbian \ 38 phone/symbian \
39 protocol \ 39 protocol \
40 protocol/nokia \ 40 protocol/nokia \
41 protocol/at \ 41 protocol/at \
42 protocol/alcatel \ 42 protocol/alcatel \
43 protocol/obex \ 43 protocol/obex \
44 protocol/symbian \ 44 protocol/symbian \
45 device/serial \ 45 device/serial \
46 device/irda \ 46 device/irda \
47 device/bluetoth \ 47 device/bluetoth \
48 service \ 48 service \
49 service/sms \ 49 service/sms \
50 service/backup \ 50 service/backup \
51 phone/nokia \ 51 phone/nokia \
52 phone 52 phone
53 53
54# Input 54# Input
55HEADERS += config.h \ 55HEADERS += config.h \
56 gammu.h \ 56 gammu.h \
57 gsmcomon.h \ 57 gsmcomon.h \
58 gsmstate.h \ 58 gsmstate.h \
59 device/devfunc.h \ 59 device/devfunc.h \
60 misc/cfg.h \ 60 misc/cfg.h \
61 misc/misc.h \ 61 misc/misc.h \
62 phone/pfunc.h \ 62 phone/pfunc.h \
63 protocol/protocol.h \ 63 protocol/protocol.h \
64 service/gsmcal.h \ 64 service/gsmcal.h \
65 service/gsmcall.h \ 65 service/gsmcall.h \
66 service/gsmdata.h \ 66 service/gsmdata.h \
67 service/gsmlogo.h \ 67 service/gsmlogo.h \
68 service/gsmmisc.h \ 68 service/gsmmisc.h \
69 service/gsmnet.h \ 69 service/gsmnet.h \
70 service/gsmpbk.h \ 70 service/gsmpbk.h \
71 service/gsmprof.h \ 71 service/gsmprof.h \
72 service/gsmring.h \ 72 service/gsmring.h \
73 device/bluetoth/affix.h \ 73 device/bluetoth/affix.h \
74 device/bluetoth/blue_w32.h \ 74 device/bluetoth/blue_w32.h \
75 device/bluetoth/bluetoth.h \ 75 device/bluetoth/bluetoth.h \
76 device/bluetoth/bluez.h \ 76 device/bluetoth/bluez.h \
77 device/irda/irda.h \ 77 device/irda/irda.h \
78 device/irda/irda_unx.h \ 78 device/irda/irda_unx.h \
79 device/irda/irda_w32.h \ 79 device/irda/irda_w32.h \
80 device/serial/ser_djg.h \ 80 device/serial/ser_djg.h \
81 device/serial/ser_unx.h \ 81 device/serial/ser_unx.h \
82 device/serial/ser_w32.h \ 82 device/serial/ser_w32.h \
83 misc/coding/coding.h \ 83 misc/coding/coding.h \
84 misc/coding/md5.h \ 84 misc/coding/md5.h \
85 phone/alcatel/alcatel.h \ 85 phone/alcatel/alcatel.h \
86 phone/at/atgen.h \ 86 phone/at/atgen.h \
87 phone/nokia/ncommon.h \ 87 phone/nokia/ncommon.h \
88 phone/nokia/nfunc.h \ 88 phone/nokia/nfunc.h \
89 phone/nokia/nfuncold.h \ 89 phone/nokia/nfuncold.h \
90 phone/obex/obexgen.h \ 90 phone/obex/obexgen.h \
91 phone/symbian/mroutgen.h \ 91 phone/symbian/mroutgen.h \
92 protocol/alcatel/alcabus.h \ 92 protocol/alcatel/alcabus.h \
93 protocol/at/at.h \ 93 protocol/at/at.h \
94 protocol/nokia/fbus2.h \ 94 protocol/nokia/fbus2.h \
95 protocol/nokia/mbus2.h \ 95 protocol/nokia/mbus2.h \
96 protocol/nokia/phonet.h \ 96 protocol/nokia/phonet.h \
97 protocol/obex/obex.h \ 97 protocol/obex/obex.h \
98 protocol/symbian/mrouter.h \ 98 protocol/symbian/mrouter.h \
99 service/backup/backgen.h \ 99 service/backup/backgen.h \
100 service/backup/backics.h \ 100 service/backup/backics.h \
101 service/backup/backldif.h \ 101 service/backup/backldif.h \
102 service/backup/backlmb.h \ 102 service/backup/backlmb.h \
103 service/backup/backtext.h \ 103 service/backup/backtext.h \
104 service/backup/backvcf.h \ 104 service/backup/backvcf.h \
105 service/backup/backvcs.h \ 105 service/backup/backvcs.h \
106 service/backup/gsmback.h \ 106 service/backup/gsmback.h \
107 service/sms/gsmems.h \ 107 service/sms/gsmems.h \
108 service/sms/gsmmulti.h \ 108 service/sms/gsmmulti.h \
109 service/sms/gsmsms.h \ 109 service/sms/gsmsms.h \
110 phone/nokia/dct3/dct3comm.h \ 110 phone/nokia/dct3/dct3comm.h \
111 phone/nokia/dct3/dct3func.h \ 111 phone/nokia/dct3/dct3func.h \
112 phone/nokia/dct3/n6110.h \ 112 phone/nokia/dct3/n6110.h \
113 phone/nokia/dct3/n7110.h \ 113 phone/nokia/dct3/n7110.h \
114 phone/nokia/dct3/n9210.h \ 114 phone/nokia/dct3/n9210.h \
115 phone/nokia/dct4/dct4func.h \ 115 phone/nokia/dct4/dct4func.h \
116 phone/nokia/dct4/n3320.h \ 116 phone/nokia/dct4/n3320.h \
117 phone/nokia/dct4/n3650.h \ 117 phone/nokia/dct4/n3650.h \
118 phone/nokia/dct4/n6510.h 118 phone/nokia/dct4/n6510.h
119SOURCES +=gsmcomon.c \ 119SOURCES +=gsmcomon.c \
120gsmstate.c \ 120gsmstate.c \
121misc/misc.c \ 121misc/misc.c \
122misc/cfg.c \ 122misc/cfg.c \
123misc/coding/coding.c \ 123misc/coding/coding.c \
124misc/coding/md5.c \ 124misc/coding/md5.c \
125service/sms/gsmsms.c \ 125service/sms/gsmsms.c \
126service/sms/gsmems.c \ 126service/sms/gsmems.c \
127service/sms/gsmmulti.c \ 127service/sms/gsmmulti.c \
128service/gsmcal.c \ 128service/gsmcal.c \
129service/gsmdata.c \ 129service/gsmdata.c \
130service/gsmpbk.c \ 130service/gsmpbk.c \
131service/gsmring.c \ 131service/gsmring.c \
132service/gsmlogo.c \ 132service/gsmlogo.c \
133service/gsmmisc.c \ 133service/gsmmisc.c \
134service/gsmnet.c \ 134service/gsmnet.c \
135service/backup/gsmback.c \ 135service/backup/gsmback.c \
136service/backup/backldif.c \ 136service/backup/backldif.c \
137service/backup/backlmb.c \ 137service/backup/backlmb.c \
138service/backup/backtext.c \ 138service/backup/backtext.c \
139service/backup/backvcs.c \ 139service/backup/backvcs.c \
140service/backup/backvcf.c \ 140service/backup/backvcf.c \
141service/backup/backics.c \ 141service/backup/backics.c \
142device/bluetoth/affix.c \ 142device/bluetoth/affix.c \
143device/bluetoth/bluez.c \ 143device/bluetoth/bluez.c \
144device/bluetoth/blue_w32.c \ 144device/bluetoth/blue_w32.c \
145device/bluetoth/bluetoth.c \ 145device/bluetoth/bluetoth.c \
146device/serial/ser_djg.c \ 146device/serial/ser_djg.c \
147device/irda/irda.c \ 147device/irda/irda.c \
148device/devfunc.c \ 148device/devfunc.c \
149protocol/at/at.c \ 149protocol/at/at.c \
150protocol/alcatel/alcabus.c \ 150protocol/alcatel/alcabus.c \
151protocol/nokia/mbus2.c \ 151protocol/nokia/mbus2.c \
152protocol/nokia/fbus2.c \ 152protocol/nokia/fbus2.c \
153protocol/nokia/phonet.c \ 153protocol/nokia/phonet.c \
154protocol/obex/obex.c \ 154protocol/obex/obex.c \
155protocol/symbian/mrouter.c \ 155protocol/symbian/mrouter.c \
156phone/pfunc.c \ 156phone/pfunc.c \
157phone/at/atgen.c \ 157phone/at/atgen.c \
158phone/at/siemens.c \ 158phone/at/siemens.c \
159phone/at/sonyeric.c \ 159phone/at/sonyeric.c \
160phone/alcatel/alcatel.c \ 160phone/alcatel/alcatel.c \
161phone/nokia/dct3/n6110.c \ 161phone/nokia/dct3/n6110.c \
162phone/nokia/dct3/n7110.c \ 162phone/nokia/dct3/n7110.c \
163phone/nokia/dct3/n9210.c \ 163phone/nokia/dct3/n9210.c \
164phone/nokia/dct3/dct3func.c \ 164phone/nokia/dct3/dct3func.c \
165phone/nokia/dct4/n3320.c \ 165phone/nokia/dct4/n3320.c \
166phone/nokia/dct4/n3650.c \ 166phone/nokia/dct4/n3650.c \
167phone/nokia/dct4/n6510.c \ 167phone/nokia/dct4/n6510.c \
168phone/nokia/dct4/dct4func.c \ 168phone/nokia/dct4/dct4func.c \
169phone/nokia/nauto.c \ 169phone/nokia/nauto.c \
170phone/nokia/nfunc.c \ 170phone/nokia/nfunc.c \
171phone/nokia/nfuncold.c \ 171phone/nokia/nfuncold.c \
172phone/obex/obexgen.c \ 172phone/obex/obexgen.c \
173phone/symbian/mroutgen.c 173phone/symbian/mroutgen.c
174 174
175DEFINES += DESKTOP_VERSION
175TARGET = microgammu 176TARGET = microgammu
176CONFIG = warn_off release console 177CONFIG = warn_off release console
177DESTDIR = ../../../bin 178DESTDIR = ../../../bin
178OBJECTS_DIR = obj/unix 179OBJECTS_DIR = obj/unix
179MOC_DIR = moc/unix 180MOC_DIR = moc/unix
180 181
181unix: { 182unix: {
182SOURCES += device/serial/ser_unx.c 183SOURCES += device/serial/ser_unx.c
183} 184}
184win32:{ 185win32:{
185SOURCES += device/serial/ser_w32.c 186SOURCES += device/serial/ser_w32.c
186} 187}
diff --git a/gammu/emb/common/service/gsmring.c b/gammu/emb/common/service/gsmring.c
index f7f7082..7df46f1 100644
--- a/gammu/emb/common/service/gsmring.c
+++ b/gammu/emb/common/service/gsmring.c
@@ -1,876 +1,880 @@
1/* (c) 2001-2004 by Marcin Wiacek */ 1/* (c) 2001-2004 by Marcin Wiacek */
2/* Based on some work from Ralf Thelen (7110 ringtones), 2/* Based on some work from Ralf Thelen (7110 ringtones),
3 * Gnokii (RTTL and SM) and others 3 * Gnokii (RTTL and SM) and others
4 */ 4 */
5 5
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h> 7#include <string.h>
8#include <ctype.h> 8#include <ctype.h>
9#include <math.h> 9#include <math.h>
10#ifdef WIN32 10#ifdef WIN32
11# include <windows.h> 11# include <windows.h>
12#endif 12#endif
13 13
14#include "../gsmcomon.h" 14#include "../gsmcomon.h"
15#include "../misc/coding/coding.h" 15#include "../misc/coding/coding.h"
16#include "../gsmstate.h" 16#include "../gsmstate.h"
17#include "gsmring.h" 17#include "gsmring.h"
18#include "sms/gsmsms.h" 18#include "sms/gsmsms.h"
19 19
20int GSM_RingNoteGetFrequency(GSM_RingNote Note) 20int GSM_RingNoteGetFrequency(GSM_RingNote Note)
21{ 21{
22 double freq=0; 22 double freq=0;
23 23
24 /* Values according to the software from http://iki.fi/too/sw/xring/ 24 /* Values according to the software from http://iki.fi/too/sw/xring/
25 * generated with: 25 * generated with:
26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)' 26 * perl -e 'print int(4400 * (2 **($_/12)) + .5)/10, "\n" for(3..14)'
27 */ 27 */
28 switch (Note.Note) { 28 switch (Note.Note) {
29 case Note_C : freq = 523.3; break; 29 case Note_C : freq = 523.3; break;
30 case Note_Cis: freq = 554.4; break; 30 case Note_Cis: freq = 554.4; break;
31 case Note_D : freq = 587.3; break; 31 case Note_D : freq = 587.3; break;
32 case Note_Dis: freq = 622.3; break; 32 case Note_Dis: freq = 622.3; break;
33 case Note_E : freq = 659.3; break; 33 case Note_E : freq = 659.3; break;
34 case Note_F : freq = 698.5; break; 34 case Note_F : freq = 698.5; break;
35 case Note_Fis: freq = 740; break; 35 case Note_Fis: freq = 740; break;
36 case Note_G : freq = 784; break; 36 case Note_G : freq = 784; break;
37 case Note_Gis: freq = 830.6; break; 37 case Note_Gis: freq = 830.6; break;
38 case Note_A : freq = 880; break; 38 case Note_A : freq = 880; break;
39 case Note_Ais: freq = 932.3; break; 39 case Note_Ais: freq = 932.3; break;
40 case Note_H : freq = 987.8; break; 40 case Note_H : freq = 987.8; break;
41 case Note_Pause: break; 41 case Note_Pause: break;
42 } 42 }
43 switch (Note.Scale) { 43 switch (Note.Scale) {
44 case Scale_440 : freq = freq / 2; break; 44 case Scale_440 : freq = freq / 2; break;
45 case Scale_880 : break; 45 case Scale_880 : break;
46 case Scale_1760: freq = freq * 2; break; 46 case Scale_1760: freq = freq * 2; break;
47 case Scale_3520: freq = freq * 4; break; 47 case Scale_3520: freq = freq * 4; break;
48 default : break; 48 default : break;
49 } 49 }
50 return (int)freq; 50 return (int)freq;
51} 51}
52 52
53int GSM_RingNoteGetFullDuration(GSM_RingNote Note) 53int GSM_RingNoteGetFullDuration(GSM_RingNote Note)
54{ 54{
55 int duration = 1; 55 int duration = 1;
56 56
57 switch (Note.Duration) { 57 switch (Note.Duration) {
58 case Duration_Full : duration = 128; break; 58 case Duration_Full : duration = 128; break;
59 case Duration_1_2 : duration = 64; break; 59 case Duration_1_2 : duration = 64; break;
60 case Duration_1_4 : duration = 32; break; 60 case Duration_1_4 : duration = 32; break;
61 case Duration_1_8 : duration = 16; break; 61 case Duration_1_8 : duration = 16; break;
62 case Duration_1_16 : duration = 8; break; 62 case Duration_1_16 : duration = 8; break;
63 case Duration_1_32 : duration = 4; break; 63 case Duration_1_32 : duration = 4; break;
64 } 64 }
65 switch (Note.DurationSpec) { 65 switch (Note.DurationSpec) {
66 case NoSpecialDuration : break; 66 case NoSpecialDuration : break;
67 case DottedNote : duration = duration * 3/2;break; 67 case DottedNote : duration = duration * 3/2;break;
68 case DoubleDottedNote : duration = duration * 9/4;break; 68 case DoubleDottedNote : duration = duration * 9/4;break;
69 case Length_2_3 : duration = duration * 2/3;break; 69 case Length_2_3 : duration = duration * 2/3;break;
70 } 70 }
71 return duration; 71 return duration;
72} 72}
73 73
74#ifndef PI 74#ifndef PI
75# define PI 3.141592654 75# define PI 3.141592654
76#endif 76#endif
77 77
78#define WAV_SAMPLE_RATE 44100 78#define WAV_SAMPLE_RATE 44100
79 79
80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone) 80GSM_Error savewav(FILE *file, GSM_Ringtone *ringtone)
81{ 81{
82 unsigned char WAV_Header[] = { 82 unsigned char WAV_Header[] = {
83 'R','I','F','F', 83 'R','I','F','F',
84 0x00,0x00,0x00,0x00,/* Length */ 84 0x00,0x00,0x00,0x00,/* Length */
85 'W','A','V','E'}; 85 'W','A','V','E'};
86 unsigned char FMT_Header[] = {'f','m','t',' ', 86 unsigned char FMT_Header[] = {'f','m','t',' ',
87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac, 87 0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x44,0xac,
88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00}; 88 0x00,0x00,0x88,0x58,0x01,0x00,0x02,0x00,0x10,0x00};
89 unsigned char DATA_Header[] = { 89 unsigned char DATA_Header[] = {
90 'd','a','t','a', 90 'd','a','t','a',
91 0x00,0x00,0x00,0x00};/* Length */ 91 0x00,0x00,0x00,0x00};/* Length */
92 short DATA_Buffer[60000]; 92 short DATA_Buffer[60000];
93 long wavfilesize; 93 long wavfilesize;
94 GSM_RingNote *Note; 94 GSM_RingNote *Note;
95 long i,j,length=0; 95 long i,j,length=0;
96 double phase=0,phase_step; 96 double phase=0,phase_step;
97 97
98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); 98 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); 99 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); 100 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
101 101
102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 102 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 103 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
104 Note = &ringtone->NoteTone.Commands[i].Note; 104 Note = &ringtone->NoteTone.Commands[i].Note;
105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5; 105 phase_step = GSM_RingNoteGetFrequency(*Note)*WAV_SAMPLE_RATE*1.5;
106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) { 106 for (j=0;j<((long)(GSM_RingNoteGetFullDuration(*Note)*WAV_SAMPLE_RATE/70));j++) {
107 /*DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));*/ 107#ifdef DESKTOP_VERSION
108 DATA_Buffer[j] = ((int)(sin(phase*PI)*50000));
109#else
110 // we have no sin on Zaurus
108 DATA_Buffer[j] = ((int)(0.5*50000)); 111 DATA_Buffer[j] = ((int)(0.5*50000));
112#endif
109 phase = phase + phase_step; 113 phase = phase + phase_step;
110 length++; 114 length++;
111 } 115 }
112 fwrite(&DATA_Buffer,sizeof(short),j,file); 116 fwrite(&DATA_Buffer,sizeof(short),j,file);
113 } 117 }
114 } 118 }
115 119
116 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2; 120 wavfilesize = sizeof(WAV_Header) + sizeof(FMT_Header) + sizeof(DATA_Header) + length*2;
117 WAV_Header[4] = ((unsigned char)wavfilesize % 256); 121 WAV_Header[4] = ((unsigned char)wavfilesize % 256);
118 WAV_Header[5] = ((unsigned char)wavfilesize / 256); 122 WAV_Header[5] = ((unsigned char)wavfilesize / 256);
119 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256)); 123 WAV_Header[6] = ((unsigned char)wavfilesize / (256*256));
120 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); 124 WAV_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
121 wavfilesize = wavfilesize - 54; 125 wavfilesize = wavfilesize - 54;
122 DATA_Header[4] = ((unsigned char)wavfilesize % 256); 126 DATA_Header[4] = ((unsigned char)wavfilesize % 256);
123 DATA_Header[5] = ((unsigned char)wavfilesize / 256); 127 DATA_Header[5] = ((unsigned char)wavfilesize / 256);
124 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256)); 128 DATA_Header[6] = ((unsigned char)wavfilesize / (256*256));
125 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256)); 129 DATA_Header[7] = ((unsigned char)wavfilesize / (256*256*256));
126 130
127 fseek( file, 0, SEEK_SET); 131 fseek( file, 0, SEEK_SET);
128 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file); 132 fwrite(&WAV_Header, 1, sizeof(WAV_Header),file);
129 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file); 133 fwrite(&FMT_Header, 1, sizeof(FMT_Header),file);
130 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file); 134 fwrite(&DATA_Header, 1, sizeof(DATA_Header),file);
131 135
132 return ERR_NONE; 136 return ERR_NONE;
133} 137}
134 138
135static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone) 139static GSM_Error savebin(FILE *file, GSM_Ringtone *ringtone)
136{ 140{
137 char nullchar=0x00; 141 char nullchar=0x00;
138 142
139 fwrite(&nullchar,1,1,file); 143 fwrite(&nullchar,1,1,file);
140 fwrite(&nullchar,1,1,file); 144 fwrite(&nullchar,1,1,file);
141 fprintf(file,"\x0C\x01\x2C"); 145 fprintf(file,"\x0C\x01\x2C");
142 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name)); 146 fprintf(file,"%s",DecodeUnicodeString(ringtone->Name));
143 fwrite(&nullchar,1,1,file); 147 fwrite(&nullchar,1,1,file);
144 fwrite(&nullchar,1,1,file); 148 fwrite(&nullchar,1,1,file);
145 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); 149 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
146 return ERR_NONE; 150 return ERR_NONE;
147} 151}
148 152
149static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone) 153static GSM_Error savepuremidi(FILE *file, GSM_Ringtone *ringtone)
150{ 154{
151 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file); 155 fwrite(ringtone->NokiaBinary.Frame,1,ringtone->NokiaBinary.Length,file);
152 return ERR_NONE; 156 return ERR_NONE;
153} 157}
154 158
155GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone) 159GSM_Error saverttl(FILE *file, GSM_Ringtone *ringtone)
156{ 160{
157 GSM_RingNoteScaleDefNoteScale; 161 GSM_RingNoteScaleDefNoteScale;
158 GSM_RingNoteDurationDefNoteDuration; 162 GSM_RingNoteDurationDefNoteDuration;
159 163
160 GSM_RingNoteStyleDefNoteStyle=0; 164 GSM_RingNoteStyleDefNoteStyle=0;
161 int DefNoteTempo=0; 165 int DefNoteTempo=0;
162 166
163 bool started = false, firstcomma = true; 167 bool started = false, firstcomma = true;
164 GSM_RingNote *Note; 168 GSM_RingNote *Note;
165 169
166 unsigned char buffer[15]; 170 unsigned char buffer[15];
167 int i,j,k=0; 171 int i,j,k=0;
168 172
169 /* Saves ringtone name */ 173 /* Saves ringtone name */
170 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name)); 174 fprintf(file,"%s:",DecodeUnicodeString(ringtone->Name));
171 175
172 /* Find the most frequently used duration */ 176 /* Find the most frequently used duration */
173 for (i=0;i<6;i++) buffer[i]=0; 177 for (i=0;i<6;i++) buffer[i]=0;
174 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 178 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
175 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 179 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
176 Note = &ringtone->NoteTone.Commands[i].Note; 180 Note = &ringtone->NoteTone.Commands[i].Note;
177 /* some durations need 2 bytes in file, some 1 */ 181 /* some durations need 2 bytes in file, some 1 */
178 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) { 182 if (Note->Duration >= Duration_Full && Note->Duration <= Duration_1_8) {
179 buffer[Note->Duration/32]++; 183 buffer[Note->Duration/32]++;
180 } 184 }
181 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) { 185 if (Note->Duration >= Duration_1_16 && Note->Duration <= Duration_1_32) {
182 buffer[Note->Duration/32]+=2; 186 buffer[Note->Duration/32]+=2;
183 } 187 }
184 } 188 }
185 } 189 }
186 /* Now find the most frequently used */ 190 /* Now find the most frequently used */
187 j=0; 191 j=0;
188 for (i=0;i<6;i++) { 192 for (i=0;i<6;i++) {
189 if (buffer[i]>j) { 193 if (buffer[i]>j) {
190 k=i; 194 k=i;
191 j=buffer[i]; 195 j=buffer[i];
192 } 196 }
193 } 197 }
194 /* Finally convert the default duration */ 198 /* Finally convert the default duration */
195 DefNoteDuration = k * 32; 199 DefNoteDuration = k * 32;
196 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); 200 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
197 switch (DefNoteDuration) { 201 switch (DefNoteDuration) {
198 case Duration_Full:fprintf(file,"d=1"); break; 202 case Duration_Full:fprintf(file,"d=1"); break;
199 case Duration_1_2 :fprintf(file,"d=2"); break; 203 case Duration_1_2 :fprintf(file,"d=2"); break;
200 case Duration_1_4 :fprintf(file,"d=4"); break; 204 case Duration_1_4 :fprintf(file,"d=4"); break;
201 case Duration_1_8 :fprintf(file,"d=8"); break; 205 case Duration_1_8 :fprintf(file,"d=8"); break;
202 case Duration_1_16:fprintf(file,"d=16");break; 206 case Duration_1_16:fprintf(file,"d=16");break;
203 case Duration_1_32:fprintf(file,"d=32");break; 207 case Duration_1_32:fprintf(file,"d=32");break;
204 } 208 }
205 209
206 /* Find the most frequently used scale */ 210 /* Find the most frequently used scale */
207 for (i=0;i<9;i++) buffer[i]=0; 211 for (i=0;i<9;i++) buffer[i]=0;
208 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 212 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
209 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 213 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
210 Note = &ringtone->NoteTone.Commands[i].Note; 214 Note = &ringtone->NoteTone.Commands[i].Note;
211 if (Note->Note!=Note_Pause && 215 if (Note->Note!=Note_Pause &&
212 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) { 216 Note->Scale >= Scale_55 && Note->Scale <= Scale_14080) {
213 buffer[Note->Scale - 1]++; 217 buffer[Note->Scale - 1]++;
214 } 218 }
215 } 219 }
216 } 220 }
217 j=0; 221 j=0;
218 for (i=0;i<9;i++) { 222 for (i=0;i<9;i++) {
219 if (buffer[i]>j) { 223 if (buffer[i]>j) {
220 k = i; 224 k = i;
221 j=buffer[i]; 225 j=buffer[i];
222 } 226 }
223 } 227 }
224 DefNoteScale = k + 1; 228 DefNoteScale = k + 1;
225 /* Save the default scale */ 229 /* Save the default scale */
226 fprintf(file,",o=%i,",DefNoteScale); 230 fprintf(file,",o=%i,",DefNoteScale);
227 dbgprintf("DefNoteScale=%d\n", DefNoteScale); 231 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
228 232
229 for (i=0;i<ringtone->NoteTone.NrCommands;i++) { 233 for (i=0;i<ringtone->NoteTone.NrCommands;i++) {
230 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue; 234 if (ringtone->NoteTone.Commands[i].Type != RING_Note) continue;
231 235
232 Note = &ringtone->NoteTone.Commands[i].Note; 236 Note = &ringtone->NoteTone.Commands[i].Note;
233 237
234 /* Trick from PPM Edit */ 238 /* Trick from PPM Edit */
235 if (Note->DurationSpec == DoubleDottedNote) { 239 if (Note->DurationSpec == DoubleDottedNote) {
236 switch (Note->Duration) { 240 switch (Note->Duration) {
237 case Duration_Full:Note->Duration = Duration_Full;break; 241 case Duration_Full:Note->Duration = Duration_Full;break;
238 case Duration_1_2 :Note->Duration = Duration_Full;break; 242 case Duration_1_2 :Note->Duration = Duration_Full;break;
239 case Duration_1_4 :Note->Duration = Duration_1_2; break; 243 case Duration_1_4 :Note->Duration = Duration_1_2; break;
240 case Duration_1_8 :Note->Duration = Duration_1_4; break; 244 case Duration_1_8 :Note->Duration = Duration_1_4; break;
241 case Duration_1_16:Note->Duration = Duration_1_8; break; 245 case Duration_1_16:Note->Duration = Duration_1_8; break;
242 case Duration_1_32:Note->Duration = Duration_1_16;break; 246 case Duration_1_32:Note->Duration = Duration_1_16;break;
243 } 247 }
244 Note->DurationSpec = NoSpecialDuration; 248 Note->DurationSpec = NoSpecialDuration;
245 } 249 }
246 250
247 if (!started) { 251 if (!started) {
248 DefNoteTempo=Note->Tempo; 252 DefNoteTempo=Note->Tempo;
249 DefNoteStyle=Note->Style; 253 DefNoteStyle=Note->Style;
250 switch (Note->Style) { 254 switch (Note->Style) {
251 case StaccatoStyle: fprintf(file,"s=S,"); break; 255 case StaccatoStyle: fprintf(file,"s=S,"); break;
252 case NaturalStyle : fprintf(file,"s=N,"); break; 256 case NaturalStyle : fprintf(file,"s=N,"); break;
253 case ContinuousStyle : break; 257 case ContinuousStyle : break;
254 } 258 }
255 /* Save the default tempo */ 259 /* Save the default tempo */
256 fprintf(file,"b=%i:",DefNoteTempo); 260 fprintf(file,"b=%i:",DefNoteTempo);
257 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo); 261 dbgprintf("DefNoteTempo=%d\n", DefNoteTempo);
258 started = true; 262 started = true;
259 firstcomma = true; 263 firstcomma = true;
260 } 264 }
261 265
262 if (!started) continue; 266 if (!started) continue;
263 267
264 if (Note->Style!=DefNoteStyle) { 268 if (Note->Style!=DefNoteStyle) {
265 /* And a separator */ 269 /* And a separator */
266 if (!firstcomma) fprintf(file,","); 270 if (!firstcomma) fprintf(file,",");
267 firstcomma = false; 271 firstcomma = false;
268 DefNoteStyle=Note->Style; 272 DefNoteStyle=Note->Style;
269 switch (Note->Style) { 273 switch (Note->Style) {
270 case StaccatoStyle : fprintf(file,"s=S"); break; 274 case StaccatoStyle : fprintf(file,"s=S"); break;
271 case NaturalStyle : fprintf(file,"s=N"); break; 275 case NaturalStyle : fprintf(file,"s=N"); break;
272 case ContinuousStyle: fprintf(file,"s=C"); break; 276 case ContinuousStyle: fprintf(file,"s=C"); break;
273 } 277 }
274 } 278 }
275 if (Note->Tempo!=DefNoteTempo) { 279 if (Note->Tempo!=DefNoteTempo) {
276 /* And a separator */ 280 /* And a separator */
277 if (!firstcomma) fprintf(file,","); 281 if (!firstcomma) fprintf(file,",");
278 firstcomma = false; 282 firstcomma = false;
279 DefNoteTempo=Note->Tempo; 283 DefNoteTempo=Note->Tempo;
280 fprintf(file,"b=%i",DefNoteTempo); 284 fprintf(file,"b=%i",DefNoteTempo);
281 } 285 }
282 /* This note has a duration different than the default. We must save it */ 286 /* This note has a duration different than the default. We must save it */
283 if (Note->Duration!=DefNoteDuration) { 287 if (Note->Duration!=DefNoteDuration) {
284 /* And a separator */ 288 /* And a separator */
285 if (!firstcomma) fprintf(file,","); 289 if (!firstcomma) fprintf(file,",");
286 firstcomma = false; 290 firstcomma = false;
287 switch (Note->Duration) { 291 switch (Note->Duration) {
288 case Duration_Full:fprintf(file,"1"); break; 292 case Duration_Full:fprintf(file,"1"); break;
289 case Duration_1_2 :fprintf(file,"2"); break; 293 case Duration_1_2 :fprintf(file,"2"); break;
290 case Duration_1_4 :fprintf(file,"4"); break; 294 case Duration_1_4 :fprintf(file,"4"); break;
291 case Duration_1_8 :fprintf(file,"8"); break; 295 case Duration_1_8 :fprintf(file,"8"); break;
292 case Duration_1_16:fprintf(file,"16");break; 296 case Duration_1_16:fprintf(file,"16");break;
293 case Duration_1_32:fprintf(file,"32");break; 297 case Duration_1_32:fprintf(file,"32");break;
294 } 298 }
295 } else { 299 } else {
296 /* And a separator */ 300 /* And a separator */
297 if (!firstcomma) fprintf(file,","); 301 if (!firstcomma) fprintf(file,",");
298 firstcomma = false; 302 firstcomma = false;
299 } 303 }
300 /* Now save the actual note */ 304 /* Now save the actual note */
301 switch (Note->Note) { 305 switch (Note->Note) {
302 case Note_C :fprintf(file,"c");break; 306 case Note_C :fprintf(file,"c");break;
303 case Note_Cis:fprintf(file,"c#");break; 307 case Note_Cis:fprintf(file,"c#");break;
304 case Note_D :fprintf(file,"d");break; 308 case Note_D :fprintf(file,"d");break;
305 case Note_Dis:fprintf(file,"d#");break; 309 case Note_Dis:fprintf(file,"d#");break;
306 case Note_E :fprintf(file,"e");break; 310 case Note_E :fprintf(file,"e");break;
307 case Note_F :fprintf(file,"f");break; 311 case Note_F :fprintf(file,"f");break;
308 case Note_Fis:fprintf(file,"f#");break; 312 case Note_Fis:fprintf(file,"f#");break;
309 case Note_G :fprintf(file,"g");break; 313 case Note_G :fprintf(file,"g");break;
310 case Note_Gis:fprintf(file,"g#");break; 314 case Note_Gis:fprintf(file,"g#");break;
311 case Note_A :fprintf(file,"a");break; 315 case Note_A :fprintf(file,"a");break;
312 case Note_Ais:fprintf(file,"a#");break; 316 case Note_Ais:fprintf(file,"a#");break;
313 case Note_H :fprintf(file,"h");break; 317 case Note_H :fprintf(file,"h");break;
314 default :fprintf(file,"p");break; /*Pause ?*/ 318 default :fprintf(file,"p");break; /*Pause ?*/
315 } 319 }
316 switch (Note->DurationSpec) { 320 switch (Note->DurationSpec) {
317 case DottedNote : fprintf(file,".");break; 321 case DottedNote : fprintf(file,".");break;
318 default : break; 322 default : break;
319 } 323 }
320 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) { 324 if (Note->Note!=Note_Pause && Note->Scale != DefNoteScale) {
321 fprintf(file,"%i",Note->Scale); 325 fprintf(file,"%i",Note->Scale);
322 } 326 }
323 } 327 }
324 return ERR_NONE; 328 return ERR_NONE;
325} 329}
326 330
327void saveimelody(FILE *file, GSM_Ringtone *ringtone) 331void saveimelody(FILE *file, GSM_Ringtone *ringtone)
328{ 332{
329 char Buffer[2000]; 333 char Buffer[2000];
330 int i=2000; 334 int i=2000;
331 335
332 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true); 336 GSM_EncodeEMSSound(*ringtone, Buffer, &i, (float)1.2, true);
333 337
334 fwrite(Buffer, 1, i, file); 338 fwrite(Buffer, 1, i, file);
335} 339}
336 340
337#ifndef ENABLE_LGPL 341#ifndef ENABLE_LGPL
338 342
339static void WriteVarLen(unsigned char* midifile, int* current, long value) 343static void WriteVarLen(unsigned char* midifile, int* current, long value)
340{ 344{
341 long buffer; 345 long buffer;
342 346
343 buffer = value & 0x7f; 347 buffer = value & 0x7f;
344 348
345 while (value >>= 7) { 349 while (value >>= 7) {
346 buffer <<= 8; 350 buffer <<= 8;
347 buffer |= 0x80; 351 buffer |= 0x80;
348 buffer += (value & 0x7f); 352 buffer += (value & 0x7f);
349 } 353 }
350 354
351 while (1) { 355 while (1) {
352 midifile[(*current)++] = (unsigned char)buffer; 356 midifile[(*current)++] = (unsigned char)buffer;
353 if (buffer & 0x80) { 357 if (buffer & 0x80) {
354 buffer >>= 8; 358 buffer >>= 8;
355 } else { 359 } else {
356 break; 360 break;
357 } 361 }
358 } 362 }
359} 363}
360 364
361#define singlepauses 365#define singlepauses
362 366
363/* FIXME: need adding tempo before each note and scale too ? */ 367/* FIXME: need adding tempo before each note and scale too ? */
364void savemid(FILE* file, GSM_Ringtone *ringtone) 368void savemid(FILE* file, GSM_Ringtone *ringtone)
365{ 369{
366 int pause = 0, current = 26, duration, i, note=0, length = 20; 370 int pause = 0, current = 26, duration, i, note=0, length = 20;
367 bool started = false; 371 bool started = false;
368 GSM_RingNote *Note; 372 GSM_RingNote *Note;
369 unsigned char midifile[3000] = { 373 unsigned char midifile[3000] = {
370 0x4D, 0x54, 0x68, 0x64, // MThd 374 0x4D, 0x54, 0x68, 0x64, // MThd
371 0x00, 0x00, 0x00, 0x06, // chunk length 375 0x00, 0x00, 0x00, 0x06, // chunk length
372 0x00, 0x00, // format 0 376 0x00, 0x00, // format 0
373 0x00, 0x01, // one track 377 0x00, 0x01, // one track
374 0x00, 0x20, // 32 per quarter note 378 0x00, 0x20, // 32 per quarter note
375 0x4D, 0x54, 0x72, 0x6B, // MTrk 379 0x4D, 0x54, 0x72, 0x6B, // MTrk
376 0x00, 0x00, 0x00, 0x00, // chunk length 380 0x00, 0x00, 0x00, 0x00, // chunk length
377 0x00, 0xFF, 0x51, 0x03, // tempo meta event 381 0x00, 0xFF, 0x51, 0x03, // tempo meta event
378 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note 382 0x00, 0x00, 0x00}; // 3 bytes for us for a quarter note
379 383
380 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) { 384 for (i = 0; i < ringtone->NoteTone.NrCommands; i++) {
381 if (ringtone->NoteTone.Commands[i].Type == RING_Note) { 385 if (ringtone->NoteTone.Commands[i].Type == RING_Note) {
382 Note = &ringtone->NoteTone.Commands[i].Note; 386 Note = &ringtone->NoteTone.Commands[i].Note;
383 if (!started) { 387 if (!started) {
384 /* readmid does not read pauses at the beginning */ 388 /* readmid does not read pauses at the beginning */
385 if (Note->Note != Note_Pause) { 389 if (Note->Note != Note_Pause) {
386 /* FIXME: we need add tempo before each note or so... */ 390 /* FIXME: we need add tempo before each note or so... */
387 long duration=60000000/Note->Tempo; 391 long duration=60000000/Note->Tempo;
388 392
389 midifile[current++] = (unsigned char)(duration >> 16); 393 midifile[current++] = (unsigned char)(duration >> 16);
390 midifile[current++] = (unsigned char)(duration >> 8); 394 midifile[current++] = (unsigned char)(duration >> 8);
391 midifile[current++] = (unsigned char)duration; 395 midifile[current++] = (unsigned char)duration;
392 396
393 started = true; 397 started = true;
394 } 398 }
395 } 399 }
396 if (!started) continue; 400 if (!started) continue;
397 duration = GSM_RingNoteGetFullDuration(*Note); 401 duration = GSM_RingNoteGetFullDuration(*Note);
398 if (Note->Note == Note_Pause) { 402 if (Note->Note == Note_Pause) {
399 pause += duration; 403 pause += duration;
400#ifdef singlepauses 404#ifdef singlepauses
401 WriteVarLen(midifile,&current,pause); 405 WriteVarLen(midifile,&current,pause);
402 pause=0; 406 pause=0;
403 midifile[current++]=0x00; // pause 407 midifile[current++]=0x00; // pause
404 midifile[current++]=0x00; 408 midifile[current++]=0x00;
405#endif 409#endif
406 } else { 410 } else {
407 if (Note->Note >= Note_C && Note->Note <= Note_H) { 411 if (Note->Note >= Note_C && Note->Note <= Note_H) {
408 note = Note->Note/16 + 12 * Note->Scale - 1; 412 note = Note->Note/16 + 12 * Note->Scale - 1;
409 } 413 }
410 414
411 WriteVarLen(midifile,&current,pause); 415 WriteVarLen(midifile,&current,pause);
412 pause=0; 416 pause=0;
413 midifile[current++]=0x90; // note on 417 midifile[current++]=0x90; // note on
414 midifile[current++]=note; 418 midifile[current++]=note;
415 midifile[current++]=0x64; // forte 419 midifile[current++]=0x64; // forte
416 420
417 WriteVarLen(midifile,&current,duration); 421 WriteVarLen(midifile,&current,duration);
418 midifile[current++]=0x80; // note off 422 midifile[current++]=0x80; // note off
419 midifile[current++]=note; 423 midifile[current++]=note;
420 midifile[current++]=0x64; 424 midifile[current++]=0x64;
421 } 425 }
422 } 426 }
423 } 427 }
424 if (pause) { 428 if (pause) {
425 WriteVarLen(midifile,&current,pause); 429 WriteVarLen(midifile,&current,pause);
426 midifile[current++]=0x00; // pause 430 midifile[current++]=0x00; // pause
427 midifile[current++]=0x00; // 431 midifile[current++]=0x00; //
428 } 432 }
429 midifile[current++] = 0x00; 433 midifile[current++] = 0x00;
430 midifile[current++] = 0xFF; // track end 434 midifile[current++] = 0xFF; // track end
431 midifile[current++] = 0x2F; 435 midifile[current++] = 0x2F;
432 midifile[current++] = 0x00; 436 midifile[current++] = 0x00;
433 midifile[length++] = (current-22) >> 8; 437 midifile[length++] = (current-22) >> 8;
434 midifile[length++] = current-22; 438 midifile[length++] = current-22;
435 439
436 fwrite(midifile,1,current,file); 440 fwrite(midifile,1,current,file);
437} 441}
438 442
439#endif 443#endif
440 444
441void saveott(FILE *file, GSM_Ringtone *ringtone) 445void saveott(FILE *file, GSM_Ringtone *ringtone)
442{ 446{
443 char Buffer[2000]; 447 char Buffer[2000];
444 int i=2000; 448 int i=2000;
445 449
446 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i); 450 GSM_EncodeNokiaRTTLRingtone(*ringtone, Buffer, &i);
447 451
448 fwrite(Buffer, 1, i, file); 452 fwrite(Buffer, 1, i, file);
449} 453}
450 454
451GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone) 455GSM_Error GSM_SaveRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
452{ 456{
453 FILE *file; 457 FILE *file;
454 458
455 file = fopen(FileName, "wb"); 459 file = fopen(FileName, "wb");
456 if (file == NULL) return ERR_CANTOPENFILE; 460 if (file == NULL) return ERR_CANTOPENFILE;
457 461
458 switch (ringtone->Format) { 462 switch (ringtone->Format) {
459 case RING_NOTETONE: 463 case RING_NOTETONE:
460 if (strstr(FileName,".ott")) { 464 if (strstr(FileName,".ott")) {
461 saveott(file,ringtone); 465 saveott(file,ringtone);
462#ifndef ENABLE_LGPL 466#ifndef ENABLE_LGPL
463 } else if (strstr(FileName,".mid")) { 467 } else if (strstr(FileName,".mid")) {
464 savemid(file,ringtone); 468 savemid(file,ringtone);
465#endif 469#endif
466 } else if (strstr(FileName,".rng")) { 470 } else if (strstr(FileName,".rng")) {
467 saveott(file,ringtone); 471 saveott(file,ringtone);
468 } else if (strstr(FileName,".imy")) { 472 } else if (strstr(FileName,".imy")) {
469 saveimelody(file,ringtone); 473 saveimelody(file,ringtone);
470 } else if (strstr(FileName,".ime")) { 474 } else if (strstr(FileName,".ime")) {
471 saveimelody(file,ringtone); 475 saveimelody(file,ringtone);
472 } else if (strstr(FileName,".wav")) { 476 } else if (strstr(FileName,".wav")) {
473 savewav(file,ringtone); 477 savewav(file,ringtone);
474 } else { 478 } else {
475 saverttl(file, ringtone); 479 saverttl(file, ringtone);
476 } 480 }
477 break; 481 break;
478 case RING_NOKIABINARY: 482 case RING_NOKIABINARY:
479 savebin(file, ringtone); 483 savebin(file, ringtone);
480 break; 484 break;
481 case RING_MIDI: 485 case RING_MIDI:
482 savepuremidi(file, ringtone); 486 savepuremidi(file, ringtone);
483 break; 487 break;
484 } 488 }
485 489
486 fclose(file); 490 fclose(file);
487 491
488 return ERR_NONE; 492 return ERR_NONE;
489} 493}
490 494
491static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone) 495static GSM_Error loadrttl(FILE *file, GSM_Ringtone *ringtone)
492{ 496{
493 GSM_RingNoteScale DefNoteScale= Scale_880; 497 GSM_RingNoteScale DefNoteScale= Scale_880;
494 GSM_RingNoteDuration DefNoteDuration= Duration_1_4; 498 GSM_RingNoteDuration DefNoteDuration= Duration_1_4;
495 GSM_RingNoteStyle DefNoteStyle= NaturalStyle; 499 GSM_RingNoteStyle DefNoteStyle= NaturalStyle;
496 int DefNoteTempo= 63, i=0; 500 int DefNoteTempo= 63, i=0;
497 501
498 unsigned char buffer[2000],Name[100]; 502 unsigned char buffer[2000],Name[100];
499 GSM_RingNote *Note; 503 GSM_RingNote *Note;
500 504
501 fread(buffer, 2000, 1, file); 505 fread(buffer, 2000, 1, file);
502 506
503 ringtone->NoteTone.NrCommands = 0; 507 ringtone->NoteTone.NrCommands = 0;
504 508
505 /* -------------- name ---------------- */ 509 /* -------------- name ---------------- */
506 while (buffer[i] != ':') { 510 while (buffer[i] != ':') {
507 if (buffer[i] == 0x00) return ERR_NONE; 511 if (buffer[i] == 0x00) return ERR_NONE;
508 i++; 512 i++;
509 } 513 }
510 if (i == 0) { 514 if (i == 0) {
511 /* This is for RTTL ringtones without name. */ 515 /* This is for RTTL ringtones without name. */
512 EncodeUnicode(ringtone->Name,"Gammu",5); 516 EncodeUnicode(ringtone->Name,"Gammu",5);
513 } else { 517 } else {
514 memcpy(Name,buffer,i); 518 memcpy(Name,buffer,i);
515 Name[i] = 0x00; 519 Name[i] = 0x00;
516 EncodeUnicode(ringtone->Name,Name,strlen(Name)); 520 EncodeUnicode(ringtone->Name,Name,strlen(Name));
517 } 521 }
518 i++; 522 i++;
519 523
520 /* --------- section with default ringtone settings ----------- */ 524 /* --------- section with default ringtone settings ----------- */
521 while(1) { 525 while(1) {
522 switch (buffer[i]) { 526 switch (buffer[i]) {
523 case ':': 527 case ':':
524 break; 528 break;
525 case 0x00: 529 case 0x00:
526 return ERR_NONE; 530 return ERR_NONE;
527 case 'd': case 'D': 531 case 'd': case 'D':
528 switch (atoi(buffer+i+2)) { 532 switch (atoi(buffer+i+2)) {
529 case 1: DefNoteDuration = Duration_Full; break; 533 case 1: DefNoteDuration = Duration_Full; break;
530 case 2: DefNoteDuration = Duration_1_2 ; break; 534 case 2: DefNoteDuration = Duration_1_2 ; break;
531 case 4: DefNoteDuration = Duration_1_4 ; break; 535 case 4: DefNoteDuration = Duration_1_4 ; break;
532 case 8: DefNoteDuration = Duration_1_8 ; break; 536 case 8: DefNoteDuration = Duration_1_8 ; break;
533 case 16: DefNoteDuration = Duration_1_16; break; 537 case 16: DefNoteDuration = Duration_1_16; break;
534 case 32: DefNoteDuration = Duration_1_32; break; 538 case 32: DefNoteDuration = Duration_1_32; break;
535 } 539 }
536 break; 540 break;
537 case 'o': case 'O': 541 case 'o': case 'O':
538 switch (atoi(buffer+i+2)) { 542 switch (atoi(buffer+i+2)) {
539 case 4: DefNoteScale = Scale_440 ; break; 543 case 4: DefNoteScale = Scale_440 ; break;
540 case 5: DefNoteScale = Scale_880 ; break; 544 case 5: DefNoteScale = Scale_880 ; break;
541 case 6: DefNoteScale = Scale_1760; break; 545 case 6: DefNoteScale = Scale_1760; break;
542 case 7: DefNoteScale = Scale_3520; break; 546 case 7: DefNoteScale = Scale_3520; break;
543 } 547 }
544 break; 548 break;
545 case 'b': case 'B': 549 case 'b': case 'B':
546 DefNoteTempo=atoi(buffer+i+2); 550 DefNoteTempo=atoi(buffer+i+2);
547 dbgprintf("Tempo = %i\n",DefNoteTempo); 551 dbgprintf("Tempo = %i\n",DefNoteTempo);
548 break; 552 break;
549 case 's': case 'S': 553 case 's': case 'S':
550 switch (buffer[i+1]) { 554 switch (buffer[i+1]) {
551 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 555 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
552 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 556 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
553 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 557 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
554 } 558 }
555 switch (buffer[i+2]) { 559 switch (buffer[i+2]) {
556 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 560 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
557 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 561 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
558 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 562 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
559 } 563 }
560 break; 564 break;
561 } 565 }
562 while (buffer[i] != ':' && buffer[i] != ',') { 566 while (buffer[i] != ':' && buffer[i] != ',') {
563 if (buffer[i] == 0x00) return ERR_NONE; 567 if (buffer[i] == 0x00) return ERR_NONE;
564 i++; 568 i++;
565 } 569 }
566 if (buffer[i] == ',') i++; 570 if (buffer[i] == ',') i++;
567 if (buffer[i] == ':') break; 571 if (buffer[i] == ':') break;
568 } 572 }
569 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration); 573 dbgprintf("DefNoteDuration=%d\n", DefNoteDuration);
570 dbgprintf("DefNoteScale=%d\n", DefNoteScale); 574 dbgprintf("DefNoteScale=%d\n", DefNoteScale);
571 i++; 575 i++;
572 576
573 /* ------------------------- notes ------------------------------ */ 577 /* ------------------------- notes ------------------------------ */
574 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) { 578 while (buffer[i] != 0x00 && ringtone->NoteTone.NrCommands != MAX_RINGTONE_NOTES) {
575 switch(buffer[i]) { 579 switch(buffer[i]) {
576 case 'z': case 'Z': 580 case 'z': case 'Z':
577 switch (buffer[i+1]) { 581 switch (buffer[i+1]) {
578 case 'd': 582 case 'd':
579 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED; 583 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLED;
580 ringtone->NoteTone.NrCommands++; 584 ringtone->NoteTone.NrCommands++;
581 break; 585 break;
582 case 'D': 586 case 'D':
583 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED; 587 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLED;
584 ringtone->NoteTone.NrCommands++; 588 ringtone->NoteTone.NrCommands++;
585 break; 589 break;
586 case 'v': 590 case 'v':
587 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra; 591 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableVibra;
588 ringtone->NoteTone.NrCommands++; 592 ringtone->NoteTone.NrCommands++;
589 break; 593 break;
590 case 'V': 594 case 'V':
591 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra; 595 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableVibra;
592 ringtone->NoteTone.NrCommands++; 596 ringtone->NoteTone.NrCommands++;
593 break; 597 break;
594 case 'l': 598 case 'l':
595 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight; 599 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_DisableLight;
596 ringtone->NoteTone.NrCommands++; 600 ringtone->NoteTone.NrCommands++;
597 break; 601 break;
598 case 'L': 602 case 'L':
599 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight; 603 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_EnableLight;
600 ringtone->NoteTone.NrCommands++; 604 ringtone->NoteTone.NrCommands++;
601 } 605 }
602 break; 606 break;
603 case 'o': case 'O': 607 case 'o': case 'O':
604 switch (buffer[i+2]) { 608 switch (buffer[i+2]) {
605 case 4: DefNoteScale = Scale_440 ; break; 609 case 4: DefNoteScale = Scale_440 ; break;
606 case 5: DefNoteScale = Scale_880 ; break; 610 case 5: DefNoteScale = Scale_880 ; break;
607 case 6: DefNoteScale = Scale_1760; break; 611 case 6: DefNoteScale = Scale_1760; break;
608 case 7: DefNoteScale = Scale_3520; break; 612 case 7: DefNoteScale = Scale_3520; break;
609 } 613 }
610 break; 614 break;
611 case 's': case 'S': 615 case 's': case 'S':
612 switch (buffer[i+1]) { 616 switch (buffer[i+1]) {
613 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 617 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
614 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 618 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
615 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 619 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
616 } 620 }
617 switch (buffer[i+2]) { 621 switch (buffer[i+2]) {
618 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break; 622 case 'C': case 'c': DefNoteStyle=ContinuousStyle;break;
619 case 'N': case 'n': DefNoteStyle=NaturalStyle; break; 623 case 'N': case 'n': DefNoteStyle=NaturalStyle; break;
620 case 'S': case 's': DefNoteStyle=StaccatoStyle; break; 624 case 'S': case 's': DefNoteStyle=StaccatoStyle; break;
621 } 625 }
622 break; 626 break;
623 default: 627 default:
624 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note; 628 ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Type = RING_Note;
625 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note; 629 Note = &ringtone->NoteTone.Commands[ringtone->NoteTone.NrCommands].Note;
626 Note->Style = DefNoteStyle; 630 Note->Style = DefNoteStyle;
627 Note->Tempo = DefNoteTempo; 631 Note->Tempo = DefNoteTempo;
628 Note->Scale = DefNoteScale; 632 Note->Scale = DefNoteScale;
629 Note->Duration = DefNoteDuration; 633 Note->Duration = DefNoteDuration;
630 Note->DurationSpec = NoSpecialDuration; 634 Note->DurationSpec = NoSpecialDuration;
631 Note->Note = Note_Pause; 635 Note->Note = Note_Pause;
632 636
633 /* Duration */ 637 /* Duration */
634 switch (atoi(buffer+i)) { 638 switch (atoi(buffer+i)) {
635 case 1: Note->Duration = Duration_Full ; break; 639 case 1: Note->Duration = Duration_Full ; break;
636 case 2: Note->Duration = Duration_1_2 ; break; 640 case 2: Note->Duration = Duration_1_2 ; break;
637 case 4: Note->Duration = Duration_1_4 ; break; 641 case 4: Note->Duration = Duration_1_4 ; break;
638 case 8: Note->Duration = Duration_1_8 ; break; 642 case 8: Note->Duration = Duration_1_8 ; break;
639 case 16: Note->Duration = Duration_1_16 ; break; 643 case 16: Note->Duration = Duration_1_16 ; break;
640 case 32: Note->Duration = Duration_1_32 ; break; 644 case 32: Note->Duration = Duration_1_32 ; break;
641 } 645 }
642 /* We skip all numbers from duration specification */ 646 /* We skip all numbers from duration specification */
643 while(isdigit(buffer[i])) i++; 647 while(isdigit(buffer[i])) i++;
644 648
645 /* Some files can have special duration here */ 649 /* Some files can have special duration here */
646 if (buffer[i]=='.') { 650 if (buffer[i]=='.') {
647 Note->DurationSpec = DottedNote; 651 Note->DurationSpec = DottedNote;
648 i++; 652 i++;
649 } 653 }
650 654
651 /* Note */ 655 /* Note */
652 /* B or b is not in specs, but I decided to put it, because 656 /* B or b is not in specs, but I decided to put it, because
653 * it's in some RTTL files. It's the same to H note */ 657 * it's in some RTTL files. It's the same to H note */
654 switch (buffer[i]) { 658 switch (buffer[i]) {
655 case 'A': case 'a': Note->Note = Note_A; break; 659 case 'A': case 'a': Note->Note = Note_A; break;
656 case 'B': case 'b': Note->Note = Note_H; break; 660 case 'B': case 'b': Note->Note = Note_H; break;
657 case 'C': case 'c': Note->Note = Note_C; break; 661 case 'C': case 'c': Note->Note = Note_C; break;
658 case 'D': case 'd': Note->Note = Note_D; break; 662 case 'D': case 'd': Note->Note = Note_D; break;
659 case 'E': case 'e': Note->Note = Note_E; break; 663 case 'E': case 'e': Note->Note = Note_E; break;
660 case 'F': case 'f': Note->Note = Note_F; break; 664 case 'F': case 'f': Note->Note = Note_F; break;
661 case 'G': case 'g': Note->Note = Note_G; break; 665 case 'G': case 'g': Note->Note = Note_G; break;
662 case 'H': case 'h': Note->Note = Note_H; break; 666 case 'H': case 'h': Note->Note = Note_H; break;
663 } 667 }
664 i++; 668 i++;
665 669
666 if (buffer[i]=='#') { 670 if (buffer[i]=='#') {
667 switch (Note->Note) { 671 switch (Note->Note) {
668 case Note_A : Note->Note = Note_Ais; break; 672 case Note_A : Note->Note = Note_Ais; break;
669 case Note_C : Note->Note = Note_Cis; break; 673 case Note_C : Note->Note = Note_Cis; break;
670 case Note_D : Note->Note = Note_Dis; break; 674 case Note_D : Note->Note = Note_Dis; break;
671 case Note_F : Note->Note = Note_Fis; break; 675 case Note_F : Note->Note = Note_Fis; break;
672 case Note_G : Note->Note = Note_Gis; break; 676 case Note_G : Note->Note = Note_Gis; break;
673 default : break; 677 default : break;
674 } 678 }
675 i++; 679 i++;
676 } 680 }
677 681
678 /* Some files can have special duration here */ 682 /* Some files can have special duration here */
679 if (buffer[i]=='.') { 683 if (buffer[i]=='.') {
680 Note->DurationSpec = DottedNote; 684 Note->DurationSpec = DottedNote;
681 i++; 685 i++;
682 } 686 }
683 687
684 /* Scale */ 688 /* Scale */
685 if (Note->Note!=Note_Pause && isdigit(buffer[i])) { 689 if (Note->Note!=Note_Pause && isdigit(buffer[i])) {
686 switch (atoi(buffer+i)) { 690 switch (atoi(buffer+i)) {
687 case 4: Note->Scale = Scale_440 ; break; 691 case 4: Note->Scale = Scale_440 ; break;
688 case 5: Note->Scale = Scale_880 ; break; 692 case 5: Note->Scale = Scale_880 ; break;
689 case 6: Note->Scale = Scale_1760; break; 693 case 6: Note->Scale = Scale_1760; break;
690 case 7: Note->Scale = Scale_3520; break; 694 case 7: Note->Scale = Scale_3520; break;
691 } 695 }
692 i++; 696 i++;
693 } 697 }
694 698
695 ringtone->NoteTone.NrCommands++; 699 ringtone->NoteTone.NrCommands++;
696 break; 700 break;
697 } 701 }
698 while (buffer[i] != ',') { 702 while (buffer[i] != ',') {
699 if (buffer[i] == 0x00) return ERR_NONE; 703 if (buffer[i] == 0x00) return ERR_NONE;
700 i++; 704 i++;
701 } 705 }
702 if (buffer[i] == ',') i++; 706 if (buffer[i] == ',') i++;
703 } 707 }
704 708
705 return ERR_NONE; 709 return ERR_NONE;
706} 710}
707 711
708static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone) 712static GSM_Error loadott(FILE *file, GSM_Ringtone *ringtone)
709{ 713{
710 char Buffer[2000]; 714 char Buffer[2000];
711 int i; 715 int i;
712 716
713 i=fread(Buffer, 1, 2000, file); 717 i=fread(Buffer, 1, 2000, file);
714 718
715 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i); 719 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer, i);
716} 720}
717 721
718static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone) 722static GSM_Error loadcommunicator(FILE *file, GSM_Ringtone *ringtone)
719{ 723{
720 char Buffer[4000]; 724 char Buffer[4000];
721 int i,j; 725 int i,j;
722 726
723 i=fread(Buffer, 1, 4000, file); 727 i=fread(Buffer, 1, 4000, file);
724 728
725 i=0;j=0; 729 i=0;j=0;
726 while (true) { 730 while (true) {
727 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 && 731 if (Buffer[j] ==0x00 && Buffer[j+1]==0x02 &&
728 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break; 732 Buffer[j+2]==0x4a && Buffer[j+3]==0x3a) break;
729 if (j==i-4) return ERR_UNKNOWN; 733 if (j==i-4) return ERR_UNKNOWN;
730 j++; 734 j++;
731 } 735 }
732 j++; 736 j++;
733 737
734 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j); 738 return GSM_DecodeNokiaRTTLRingtone(ringtone, Buffer+j, i-j);
735} 739}
736 740
737static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone) 741static GSM_Error loadbin(FILE *file, GSM_Ringtone *ringtone)
738{ 742{
739 int i; 743 int i;
740 unsigned charbuffer[2000]; 744 unsigned charbuffer[2000];
741 745
742 dbgprintf("loading binary\n"); 746 dbgprintf("loading binary\n");
743 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); 747 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
744 i=5; 748 i=5;
745 while (buffer[i]!=0x00) i++; 749 while (buffer[i]!=0x00) i++;
746 EncodeUnicode(ringtone->Name,buffer+5,i-5); 750 EncodeUnicode(ringtone->Name,buffer+5,i-5);
747 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) { 751 while (buffer[i]!=0x02 && buffer[i+1]!=0xFC && buffer[i+2]!=0x09) {
748 i++; 752 i++;
749 } 753 }
750 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i; 754 ringtone->NokiaBinary.Length=ringtone->NokiaBinary.Length-i;
751 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length); 755 memcpy(ringtone->NokiaBinary.Frame,buffer+i,ringtone->NokiaBinary.Length);
752 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); 756 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
753 return ERR_NONE; 757 return ERR_NONE;
754} 758}
755 759
756static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone) 760static GSM_Error loadpuremidi(FILE *file, GSM_Ringtone *ringtone)
757{ 761{
758 unsigned char buffer[30000]; 762 unsigned char buffer[30000];
759 763
760 dbgprintf("loading midi\n"); 764 dbgprintf("loading midi\n");
761 EncodeUnicode(ringtone->Name,"MIDI",4); 765 EncodeUnicode(ringtone->Name,"MIDI",4);
762 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file); 766 ringtone->NokiaBinary.Length=fread(buffer, 1, 30000, file);
763 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length); 767 memcpy(ringtone->NokiaBinary.Frame,buffer,ringtone->NokiaBinary.Length);
764 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name)); 768 dbgprintf("Length %i name \"%s\"\n",ringtone->NokiaBinary.Length,DecodeUnicodeString(ringtone->Name));
765 return ERR_NONE; 769 return ERR_NONE;
766} 770}
767 771
768static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone) 772static GSM_Error loadre(FILE *file, GSM_Ringtone *ringtone)
769{ 773{
770 unsigned char buffer[2000]; 774 unsigned char buffer[2000];
771 775
772 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file); 776 ringtone->NokiaBinary.Length=fread(buffer, 1, 500, file);
773 777
774 if (buffer[18]==0x00 && buffer[21]!=0x02) { 778 if (buffer[18]==0x00 && buffer[21]!=0x02) {
775 /* DCT3, Unicode subformat, 62xx & 7110 */ 779 /* DCT3, Unicode subformat, 62xx & 7110 */
776 CopyUnicodeString(ringtone->Name,buffer+18); 780 CopyUnicodeString(ringtone->Name,buffer+18);
777 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2); 781 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (21+UnicodeLength(ringtone->Name)*2);
778 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length); 782 memcpy(ringtone->NokiaBinary.Frame,buffer+21+UnicodeLength(ringtone->Name)*2,ringtone->NokiaBinary.Length);
779 } else { 783 } else {
780 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */ 784 /* DCT3, normal subformat, 32xx/33xx/51xx/5210/5510/61xx/8xxx */
781 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]); 785 EncodeUnicode(ringtone->Name,buffer+17,buffer[16]);
782 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name)); 786 ringtone->NokiaBinary.Length = ringtone->NokiaBinary.Length - (19+UnicodeLength(ringtone->Name));
783 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length); 787 memcpy(ringtone->NokiaBinary.Frame,buffer+19+UnicodeLength(ringtone->Name),ringtone->NokiaBinary.Length);
784 } 788 }
785 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name)); 789 dbgprintf("Name \"%s\"\n",DecodeUnicodeString(ringtone->Name));
786 return ERR_NONE; 790 return ERR_NONE;
787} 791}
788 792
789GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone) 793GSM_Error GSM_ReadRingtoneFile(char *FileName, GSM_Ringtone *ringtone)
790{ 794{
791 FILE *file; 795 FILE *file;
792 unsigned charbuffer[300]; 796 unsigned charbuffer[300];
793 GSM_Errorerror = ERR_UNKNOWN; 797 GSM_Errorerror = ERR_UNKNOWN;
794 798
795 dbgprintf("Loading ringtone %s\n",FileName); 799 dbgprintf("Loading ringtone %s\n",FileName);
796 file = fopen(FileName, "rb"); 800 file = fopen(FileName, "rb");
797 if (file == NULL) return ERR_CANTOPENFILE; 801 if (file == NULL) return ERR_CANTOPENFILE;
798 802
799 /* Read the header of the file. */ 803 /* Read the header of the file. */
800 fread(buffer, 1, 4, file); 804 fread(buffer, 1, 4, file);
801 if (ringtone->Format == 0x00) { 805 if (ringtone->Format == 0x00) {
802 ringtone->Format = RING_NOTETONE; 806 ringtone->Format = RING_NOTETONE;
803 if (buffer[0]==0x00 && buffer[1]==0x00 && 807 if (buffer[0]==0x00 && buffer[1]==0x00 &&
804 buffer[2]==0x0C && buffer[3]==0x01) { 808 buffer[2]==0x0C && buffer[3]==0x01) {
805 ringtone->Format = RING_NOKIABINARY; 809 ringtone->Format = RING_NOKIABINARY;
806 } 810 }
807 if (buffer[0]==0x00 && buffer[1]==0x00 && 811 if (buffer[0]==0x00 && buffer[1]==0x00 &&
808 buffer[2]==0x00) { 812 buffer[2]==0x00) {
809 ringtone->Format = RING_NOKIABINARY; 813 ringtone->Format = RING_NOKIABINARY;
810 } 814 }
811 if (buffer[0]==0x4D && buffer[1]==0x54 && 815 if (buffer[0]==0x4D && buffer[1]==0x54 &&
812 buffer[2]==0x68 && buffer[3]==0x64) { 816 buffer[2]==0x68 && buffer[3]==0x64) {
813 ringtone->Format = RING_MIDI; 817 ringtone->Format = RING_MIDI;
814 } 818 }
815 } 819 }
816 rewind(file); 820 rewind(file);
817 switch (ringtone->Format) { 821 switch (ringtone->Format) {
818 case RING_NOTETONE: 822 case RING_NOTETONE:
819 if (buffer[0]==0x02 && buffer[1]==0x4A) { 823 if (buffer[0]==0x02 && buffer[1]==0x4A) {
820 error=loadott(file,ringtone); 824 error=loadott(file,ringtone);
821 } else if (buffer[0]==0xC7 && buffer[1]==0x45) { 825 } else if (buffer[0]==0xC7 && buffer[1]==0x45) {
822 error=loadcommunicator(file,ringtone); 826 error=loadcommunicator(file,ringtone);
823 } else { 827 } else {
824 error=loadrttl(file,ringtone); 828 error=loadrttl(file,ringtone);
825 } 829 }
826 ringtone->NoteTone.AllNotesScale=false; 830 ringtone->NoteTone.AllNotesScale=false;
827 break; 831 break;
828 case RING_NOKIABINARY: 832 case RING_NOKIABINARY:
829 if (buffer[0]==0x00 && buffer[1]==0x00 && 833 if (buffer[0]==0x00 && buffer[1]==0x00 &&
830 buffer[2]==0x0C && buffer[3]==0x01) { 834 buffer[2]==0x0C && buffer[3]==0x01) {
831 error=loadbin(file,ringtone); 835 error=loadbin(file,ringtone);
832 } 836 }
833 if (buffer[0]==0x00 && buffer[1]==0x00 && 837 if (buffer[0]==0x00 && buffer[1]==0x00 &&
834 buffer[2]==0x00) { 838 buffer[2]==0x00) {
835 error=loadre(file,ringtone); 839 error=loadre(file,ringtone);
836 } 840 }
837 break; 841 break;
838 case RING_MIDI: 842 case RING_MIDI:
839 EncodeUnicode(ringtone->Name,FileName,strlen(FileName)); 843 EncodeUnicode(ringtone->Name,FileName,strlen(FileName));
840 error = loadpuremidi(file,ringtone); 844 error = loadpuremidi(file,ringtone);
841 } 845 }
842 fclose(file); 846 fclose(file);
843 return(error); 847 return(error);
844} 848}
845 849
846/* -------------------------- required with Nokia & RTTL ------------------- */ 850/* -------------------------- required with Nokia & RTTL ------------------- */
847 851
848/* Beats per Minute like written in Smart Messaging */ 852/* Beats per Minute like written in Smart Messaging */
849static int SM_BeatsPerMinute[] = { 853static int SM_BeatsPerMinute[] = {
850 25, 28, 31, 35, 40, 45, 50, 56, 63,70, 854 25, 28, 31, 35, 40, 45, 50, 56, 63,70,
851 80, 90, 100, 112, 125, 140, 160, 180, 200,225, 855 80, 90, 100, 112, 125, 140, 160, 180, 200,225,
852 250, 285, 320, 355, 400, 450, 500, 565, 635,715, 856 250, 285, 320, 355, 400, 450, 500, 565, 635,715,
853 800,900 857 800,900
854}; 858};
855 859
856int GSM_RTTLGetTempo(int Beats) 860int GSM_RTTLGetTempo(int Beats)
857{ 861{
858 int i=0; 862 int i=0;
859 863
860 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++; 864 while (Beats > SM_BeatsPerMinute[i] && SM_BeatsPerMinute[i] != 900) i++;
861 865
862 return i<<3; 866 return i<<3;
863} 867}
864 868
865/* This function packs the ringtone from the structure "ringtone" to 869/* This function packs the ringtone from the structure "ringtone" to
866 "package", where maxlength means length of package. 870 "package", where maxlength means length of package.
867 Function returns number of packed notes and change maxlength to 871 Function returns number of packed notes and change maxlength to
868 number of used chars in "package" */ 872 number of used chars in "package" */
869unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength) 873unsigned char GSM_EncodeNokiaRTTLRingtone(GSM_Ringtone ringtone, unsigned char *package, int *maxlength)
870{ 874{
871 unsigned char CommandLength = 0x02; 875 unsigned char CommandLength = 0x02;
872 unsigned char Loop = 0x15;/* Infinite */ 876 unsigned char Loop = 0x15;/* Infinite */
873 877
874 unsigned char Buffer[200]; 878 unsigned char Buffer[200];
875 int StartBit=0, OldStartBit; 879 int StartBit=0, OldStartBit;
876 int StartBitHowManyCommands; 880 int StartBitHowManyCommands;