62 |
62 |
63 const uint DISABLE_LOCAL_AREA_COVERAGE_MASK = 0x0800; |
63 const uint DISABLE_LOCAL_AREA_COVERAGE_MASK = 0x0800; |
64 |
64 |
65 const int PS_NAME_CHANGE_THRESHOLD_SECONDS = 10; |
65 const int PS_NAME_CHANGE_THRESHOLD_SECONDS = 10; |
66 |
66 |
|
67 // Macros to help protect shared null and manual station instances to help debugging |
|
68 // Enabled in emulator or win32 builds by default |
|
69 #if defined __WINS__ || defined BUILD_WIN32 |
|
70 # define PROTECT_SHAREDNULL_AND_MANUALSTATION |
|
71 #endif |
|
72 |
|
73 #ifdef PROTECT_SHAREDNULL_AND_MANUALSTATION |
|
74 # define ASSERT_SHARED_NULL_IS_INTACT \ |
|
75 Q_ASSERT_X( mData->mPresetIndex != SharedNull, "RadioStation", "Shared null modified illegally!" ); |
|
76 # define ASSERT_MANUAL_STATION \ |
|
77 Q_ASSERT_X( mData->mPresetIndex != ManualStation, "RadioStation", "Illegally modifying manual station" ); |
|
78 #else |
|
79 # define ASSERT_SHARED_NULL_IS_INTACT |
|
80 # define ASSERT_MANUAL_STATION |
|
81 #endif // PROTECT_SHAREDNULL_AND_MANUALSTATION |
|
82 |
67 /** |
83 /** |
68 * Static shared data instance that is used by all default-constructed RadioStation instances |
84 * Static shared data instance that is used by all default-constructed RadioStation instances |
69 */ |
85 */ |
70 Q_GLOBAL_STATIC_WITH_ARGS( RadioStationPrivate, shared_null, ( RadioStation::SharedNull ) ) |
86 static RadioStationPrivate shared_null( RadioStation::SharedNull, 0 ); |
71 |
87 |
72 /*! |
88 /*! |
73 * |
89 * |
74 */ |
90 */ |
75 QString RadioStation::parseFrequency( uint frequency ) |
91 QString RadioStation::parseFrequency( uint frequency ) |
81 |
97 |
82 /*! |
98 /*! |
83 * |
99 * |
84 */ |
100 */ |
85 RadioStation::RadioStation() : |
101 RadioStation::RadioStation() : |
86 QObject( 0 ) |
102 mData( &shared_null ) |
87 { |
103 { |
88 mData = shared_null(); |
|
89 mData->ref.ref(); |
|
90 } |
104 } |
91 |
105 |
92 /*! |
106 /*! |
93 * |
107 * |
94 */ |
108 */ |
95 RadioStation::RadioStation( const RadioStation& other ) : |
109 RadioStation::RadioStation( const RadioStation& other ) : |
96 QObject( 0 ) |
110 mData( other.mData ) |
|
111 { |
|
112 } |
|
113 |
|
114 /*! |
|
115 * |
|
116 */ |
|
117 RadioStation::RadioStation( int presetIndex, uint frequency ) : |
|
118 mData( new RadioStationPrivate( presetIndex, frequency ) ) |
|
119 { |
|
120 } |
|
121 |
|
122 /*! |
|
123 * |
|
124 */ |
|
125 RadioStation::~RadioStation() |
|
126 { |
|
127 } |
|
128 |
|
129 /*! |
|
130 * |
|
131 */ |
|
132 RadioStation& RadioStation::operator=( const RadioStation& other ) |
97 { |
133 { |
98 mData = other.mData; |
134 mData = other.mData; |
99 mData->ref.ref(); |
|
100 } |
|
101 |
|
102 /*! |
|
103 * |
|
104 */ |
|
105 RadioStation::RadioStation( int presetIndex, uint frequency ) : |
|
106 QObject( 0 ) |
|
107 { |
|
108 mData = new RadioStationPrivate( presetIndex, frequency ); |
|
109 } |
|
110 |
|
111 /*! |
|
112 * |
|
113 */ |
|
114 RadioStation::~RadioStation() |
|
115 { |
|
116 decrementReferenceCount(); |
|
117 } |
|
118 |
|
119 /*! |
|
120 * |
|
121 */ |
|
122 RadioStation& RadioStation::operator=( const RadioStation& other ) |
|
123 { |
|
124 qAtomicAssign( mData, other.mData ); |
|
125 return *this; |
135 return *this; |
126 } |
136 } |
127 |
137 |
128 /*! |
138 /*! |
129 * |
139 * |
130 */ |
140 */ |
131 void RadioStation::reset() |
141 void RadioStation::reset() |
132 { |
142 { |
133 decrementReferenceCount(); |
143 mData = &shared_null; |
134 mData = shared_null(); |
144 ASSERT_SHARED_NULL_IS_INTACT |
135 mData->ref.ref(); |
|
136 } |
145 } |
137 |
146 |
138 /*! |
147 /*! |
139 * |
148 * |
140 */ |
149 */ |
141 void RadioStation::setChangeFlags( RadioStation::Change flags ) |
150 void RadioStation::setChangeFlags( RadioStation::Change flags ) |
142 { |
151 { |
143 if ( mData->mChangeFlags != flags ) { |
152 if ( mData->mChangeFlags != flags ) { |
144 detach(); |
|
145 mData->mChangeFlags = flags; |
153 mData->mChangeFlags = flags; |
146 } |
154 } |
147 } |
155 } |
148 |
156 |
149 /*! |
157 /*! |
150 * |
158 * |
151 */ |
159 */ |
152 void RadioStation::setPresetIndex( int presetIndex ) |
160 void RadioStation::setPresetIndex( int presetIndex ) |
153 { |
161 { |
154 if ( mData->mPresetIndex != presetIndex ) { |
162 if ( mData->mPresetIndex != presetIndex ) { |
155 detach(); |
163 ASSERT_MANUAL_STATION |
156 mData->mPresetIndex = presetIndex; |
164 mData->mPresetIndex = presetIndex; |
157 mData->mChangeFlags |= RadioStation::PersistentDataChanged; |
165 mData->mChangeFlags |= RadioStation::PersistentDataChanged; |
158 } |
166 } |
159 } |
167 } |
160 |
168 |
176 void RadioStation::setName( const QString& name ) |
184 void RadioStation::setName( const QString& name ) |
177 { |
185 { |
178 // Name emptiness is checked because this name setter is used by incoming RDS PS name |
186 // Name emptiness is checked because this name setter is used by incoming RDS PS name |
179 // and empty names should be ignored |
187 // and empty names should be ignored |
180 if ( !name.isEmpty() && !mData->mRenamedByUser && mData->mName.compare( name ) != 0 ) { |
188 if ( !name.isEmpty() && !mData->mRenamedByUser && mData->mName.compare( name ) != 0 ) { |
181 detach(); |
|
182 mData->mName = name.trimmed(); |
189 mData->mName = name.trimmed(); |
183 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::NameChanged; |
190 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::NameChanged; |
184 |
191 |
185 // Save the time when PS name changed and if the last change was too close to the current time |
192 // Save the time when PS name changed and if the last change was too close to the current time |
186 // change the PS type to dynamic if it has already been incorrectly determined to be static. |
193 // change the PS type to dynamic if it has already been incorrectly determined to be static. |
201 mData->mUrl = "<a href=\"buu\">www." + mData->mName.toLower() + ".fi</a>"; |
208 mData->mUrl = "<a href=\"buu\">www." + mData->mName.toLower() + ".fi</a>"; |
202 } else { |
209 } else { |
203 mData->mUrl = ""; |
210 mData->mUrl = ""; |
204 } |
211 } |
205 mData->mChangeFlags |= RadioStation::UrlChanged; |
212 mData->mChangeFlags |= RadioStation::UrlChanged; |
|
213 ASSERT_SHARED_NULL_IS_INTACT |
206 } |
214 } |
207 } |
215 } |
208 |
216 |
209 /*! |
217 /*! |
210 * |
218 * |
211 */ |
219 */ |
212 void RadioStation::setGenre( const int genre ) |
220 void RadioStation::setGenre( const int genre ) |
213 { |
221 { |
214 if ( mData->mGenre != genre ) { |
222 if ( mData->mGenre != genre ) { |
215 detach(); |
|
216 mData->mGenre = genre; |
223 mData->mGenre = genre; |
217 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::GenreChanged; |
224 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::GenreChanged; |
|
225 ASSERT_SHARED_NULL_IS_INTACT |
218 } |
226 } |
219 } |
227 } |
220 |
228 |
221 /*! |
229 /*! |
222 * |
230 * |
223 */ |
231 */ |
224 void RadioStation::setUrl( const QString& url ) |
232 void RadioStation::setUrl( const QString& url ) |
225 { |
233 { |
226 if ( mData->mUrl.compare( url ) != 0 ) { |
234 if ( mData->mUrl.compare( url ) != 0 ) { |
227 detach(); |
|
228 mData->mUrl = url; |
235 mData->mUrl = url; |
229 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::UrlChanged; |
236 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::UrlChanged; |
|
237 ASSERT_SHARED_NULL_IS_INTACT |
230 } |
238 } |
231 } |
239 } |
232 |
240 |
233 /*! |
241 /*! |
234 * Sets the PI code |
242 * Sets the PI code |
236 */ |
244 */ |
237 bool RadioStation::setPiCode( int piCode, RadioRegion::Region region ) |
245 bool RadioStation::setPiCode( int piCode, RadioRegion::Region region ) |
238 { |
246 { |
239 LOG_FORMAT( "RadioStation::setPiCode new PI: %d", piCode ); |
247 LOG_FORMAT( "RadioStation::setPiCode new PI: %d", piCode ); |
240 // toggling local area coverage bit code must not be interpreted as new PI code |
248 // toggling local area coverage bit code must not be interpreted as new PI code |
241 if( region != RadioRegion::America ) |
249 if ( region != RadioRegion::America ) { |
242 { |
|
243 piCode &= ~DISABLE_LOCAL_AREA_COVERAGE_MASK; |
250 piCode &= ~DISABLE_LOCAL_AREA_COVERAGE_MASK; |
244 } |
251 } |
245 |
252 |
246 LOG_FORMAT( "stored PI: %d", mData->mPiCode ); |
253 LOG_FORMAT( "stored PI: %d", mData->mPiCode ); |
247 LOG_FORMAT( "call sign check done: %d", mData->mCallSignCheckDone ); |
254 LOG_FORMAT( "call sign check done: %d", mData->mCallSignCheckDone ); |
248 //prevent executing the below code when unnessesary |
255 //prevent executing the below code when unnessesary |
249 if ( mData->mPiCode != piCode || !mData->mCallSignCheckDone ) |
256 if ( mData->mPiCode != piCode || !mData->mCallSignCheckDone ) { |
250 { |
|
251 detach(); |
|
252 mData->mPiCode = piCode; |
257 mData->mPiCode = piCode; |
253 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::PiCodeChanged; |
258 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::PiCodeChanged; |
254 // call sign not calculated for clear channel stations |
259 // call sign not calculated for clear channel stations |
255 //TODO: Remove magic numbers |
260 //TODO: Remove magic numbers |
256 if( ( (mData->mPiCode & 0xF000 ) >> 12 ) == 0x1 ) |
261 if ( ( (mData->mPiCode & 0xF000 ) >> 12 ) == 0x1 ) { |
257 { |
|
258 LOG( "Clear channel station" ); |
262 LOG( "Clear channel station" ); |
259 mData->mCallSignCheckDone = true; |
263 mData->mCallSignCheckDone = true; |
260 } |
264 } else if ( region == RadioRegion::America && mData->mName.isEmpty() && !isRenamed() ) { |
261 // if America region, not PS name received and not user renamed station |
|
262 else if ( region == RadioRegion::America && mData->mName.isEmpty() && !isRenamed() ) |
|
263 { |
|
264 LOG( "Calculate call sign" ); |
265 LOG( "Calculate call sign" ); |
265 mData->mName = piCodeToCallSign( mData->mPiCode ); |
266 mData->mName = piCodeToCallSign( mData->mPiCode ); |
266 mData->mChangeFlags |= RadioStation::NameChanged; |
267 mData->mChangeFlags |= RadioStation::NameChanged; |
267 } |
268 } |
268 |
269 |
269 if ( mData->mChangeFlags.testFlag( RadioStation::PsTypeChanged ) ) |
270 if ( mData->mChangeFlags.testFlag( RadioStation::PsTypeChanged ) ) { |
270 { |
|
271 LOG( "Call sign check done" ); |
271 LOG( "Call sign check done" ); |
272 mData->mCallSignCheckDone = true; |
272 mData->mCallSignCheckDone = true; |
273 } |
273 } |
274 |
274 |
|
275 ASSERT_SHARED_NULL_IS_INTACT |
275 return true; |
276 return true; |
276 } |
277 } |
277 return false; |
278 return false; |
278 } |
279 } |
279 |
280 |
281 * |
282 * |
282 */ |
283 */ |
283 void RadioStation::setPsType( PsType psType ) |
284 void RadioStation::setPsType( PsType psType ) |
284 { |
285 { |
285 if ( mData->mPsType != psType ) { |
286 if ( mData->mPsType != psType ) { |
286 detach(); |
|
287 mData->mPsType = psType; |
287 mData->mPsType = psType; |
288 mData->mChangeFlags |= RadioStation::PsTypeChanged; |
288 mData->mChangeFlags |= RadioStation::PsTypeChanged; |
|
289 ASSERT_SHARED_NULL_IS_INTACT |
289 } |
290 } |
290 } |
291 } |
291 |
292 |
292 /*! |
293 /*! |
293 * |
294 * |
294 */ |
295 */ |
295 void RadioStation::setRadioText( const QString& radioText ) |
296 void RadioStation::setRadioText( const QString& radioText ) |
296 { |
297 { |
297 if ( mData->mRadioText.compare( radioText ) != 0 ) { |
298 if ( mData->mRadioText.compare( radioText ) != 0 ) { |
298 detach(); |
|
299 mData->mRadioText = radioText.isEmpty() ? "" : radioText.trimmed(); |
299 mData->mRadioText = radioText.isEmpty() ? "" : radioText.trimmed(); |
300 mData->mChangeFlags |= RadioStation::RadioTextChanged; |
300 mData->mChangeFlags |= RadioStation::RadioTextChanged; |
|
301 ASSERT_SHARED_NULL_IS_INTACT |
301 } |
302 } |
302 } |
303 } |
303 |
304 |
304 /*! |
305 /*! |
305 * |
306 * |
314 if ( rtPlusClass == RtPlus::Homepage ) { |
315 if ( rtPlusClass == RtPlus::Homepage ) { |
315 setUrl( rtPlusItem ); |
316 setUrl( rtPlusItem ); |
316 return; |
317 return; |
317 } |
318 } |
318 |
319 |
319 detach(); |
|
320 QString replacement = ""; |
320 QString replacement = ""; |
321 if ( rtPlusClass == RtPlus::Artist ) { |
321 if ( rtPlusClass == RtPlus::Artist ) { |
322 replacement = HTML_ARTIST; |
322 replacement = HTML_ARTIST; |
323 } else if ( rtPlusClass == RtPlus::Title ) { |
323 } else if ( rtPlusClass == RtPlus::Title ) { |
324 replacement = HTML_TITLE; |
324 replacement = HTML_TITLE; |
334 * |
334 * |
335 */ |
335 */ |
336 void RadioStation::setDynamicPsText( const QString& dynamicPsText ) |
336 void RadioStation::setDynamicPsText( const QString& dynamicPsText ) |
337 { |
337 { |
338 if ( mData->mDynamicPsText.compare( dynamicPsText ) != 0 ) { |
338 if ( mData->mDynamicPsText.compare( dynamicPsText ) != 0 ) { |
339 detach(); |
|
340 mData->mDynamicPsText = dynamicPsText; |
339 mData->mDynamicPsText = dynamicPsText; |
341 mData->mChangeFlags |= RadioStation::DynamicPsChanged; |
340 mData->mChangeFlags |= RadioStation::DynamicPsChanged; |
|
341 ASSERT_SHARED_NULL_IS_INTACT |
342 } |
342 } |
343 } |
343 } |
344 |
344 |
345 /*! |
345 /*! |
346 * |
346 * |
347 */ |
347 */ |
348 bool RadioStation::isValid() const |
348 bool RadioStation::isValid() const |
349 { |
349 { |
350 return mData->mPresetIndex >= 0 && mData->mFrequency > 0; |
350 return mData->mFrequency > 0 && ( isType( ManualStation ) || mData->mPresetIndex >= 0 ); |
351 } |
351 } |
352 |
352 |
353 /*! |
353 /*! |
354 * |
354 * |
355 */ |
355 */ |
364 void RadioStation::setUserDefinedName( const QString& name ) |
364 void RadioStation::setUserDefinedName( const QString& name ) |
365 { |
365 { |
366 // We don't check for name emptiness because this setter is used also to remove the renaming |
366 // We don't check for name emptiness because this setter is used also to remove the renaming |
367 // of a station by setting an empty name |
367 // of a station by setting an empty name |
368 if ( mData->mName.compare( name ) != 0 ) { |
368 if ( mData->mName.compare( name ) != 0 ) { |
369 detach(); |
|
370 mData->mName = name; |
369 mData->mName = name; |
371 mData->mRenamedByUser = !name.isEmpty(); |
370 mData->mRenamedByUser = !name.isEmpty(); |
372 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::NameChanged; |
371 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::NameChanged; |
373 } |
372 } |
374 } |
373 } |
464 * |
452 * |
465 */ |
453 */ |
466 bool RadioStation::hasRds() const |
454 bool RadioStation::hasRds() const |
467 { |
455 { |
468 return hasPiCode() || |
456 return hasPiCode() || |
469 mData->mGenre != -1 || |
457 mData->mGenre != -1 || |
470 !mData->mDynamicPsText.isEmpty() || |
458 !mData->mDynamicPsText.isEmpty() || |
471 !mData->mRadioText.isEmpty() || |
459 !mData->mRadioText.isEmpty() || |
472 ( !mData->mName.isEmpty() && !isRenamed() ); |
460 ( !mData->mName.isEmpty() && !isRenamed() ); |
473 } |
461 } |
474 |
462 |
475 /*! |
463 /*! |
476 * |
464 * |
477 */ |
465 */ |
478 void RadioStation::setType( RadioStation::Type type ) |
466 void RadioStation::setType( RadioStation::Type type ) |
479 { |
467 { |
480 if ( !isType( type ) ) { |
468 if ( !isType( type ) ) { |
481 detach(); |
|
482 |
469 |
483 // Check if favorite-status changed |
470 // Check if favorite-status changed |
484 if ( mData->mType.testFlag( RadioStation::Favorite ) != type.testFlag( RadioStation::Favorite ) ) { |
471 if ( mData->mType.testFlag( RadioStation::Favorite ) != type.testFlag( RadioStation::Favorite ) ) { |
485 mData->mChangeFlags |= RadioStation::FavoriteChanged; |
472 mData->mChangeFlags |= RadioStation::FavoriteChanged; |
486 } |
473 } |
487 |
474 |
488 mData->mType |= type; |
475 mData->mType |= type; |
489 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::TypeChanged; |
476 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::TypeChanged; |
|
477 ASSERT_SHARED_NULL_IS_INTACT |
490 } |
478 } |
491 } |
479 } |
492 |
480 |
493 /*! |
481 /*! |
494 * |
482 * |
495 */ |
483 */ |
496 void RadioStation::unsetType( RadioStation::Type type ) |
484 void RadioStation::unsetType( RadioStation::Type type ) |
497 { |
485 { |
498 if ( isType( type ) ) { |
486 if ( isType( type ) ) { |
499 detach(); |
|
500 |
487 |
501 // Check if favorite-status changed |
488 // Check if favorite-status changed |
502 if ( mData->mType.testFlag( RadioStation::Favorite ) != type.testFlag( RadioStation::Favorite ) ) { |
489 if ( mData->mType.testFlag( RadioStation::Favorite ) != type.testFlag( RadioStation::Favorite ) ) { |
503 mData->mChangeFlags |= RadioStation::FavoriteChanged; |
490 mData->mChangeFlags |= RadioStation::FavoriteChanged; |
504 } |
491 } |
505 |
492 |
506 mData->mType &= ~type; |
493 mData->mType &= ~type; |
507 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::TypeChanged; |
494 mData->mChangeFlags |= RadioStation::PersistentDataChanged | RadioStation::TypeChanged; |
|
495 ASSERT_SHARED_NULL_IS_INTACT |
508 } |
496 } |
509 } |
497 } |
510 |
498 |
511 /*! |
499 /*! |
512 * |
500 * |
593 { |
569 { |
594 QString callSign; |
570 QString callSign; |
595 |
571 |
596 LOG_FORMAT( "RadioStation::piCodeToCallSign PI: %d", programmeIdentification ); |
572 LOG_FORMAT( "RadioStation::piCodeToCallSign PI: %d", programmeIdentification ); |
597 // call signs beginning with 'K' |
573 // call signs beginning with 'K' |
598 if( ( programmeIdentification>=KXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification < WXXX_CALLSIGN_PI_FIRST ) ) { |
574 if ( ( programmeIdentification>=KXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification < WXXX_CALLSIGN_PI_FIRST ) ) { |
599 callSign += "K"; |
575 callSign += "K"; |
600 callSign += iterateCallSign( KXXX_CALLSIGN_PI_FIRST, programmeIdentification ); |
576 callSign += iterateCallSign( KXXX_CALLSIGN_PI_FIRST, programmeIdentification ); |
601 } |
577 } |
602 // call signs beginning with 'W' |
578 // call signs beginning with 'W' |
603 else if (( programmeIdentification >= WXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= WXXX_CALLSIGN_PI_LAST )) { |
579 else if ( ( programmeIdentification >= WXXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= WXXX_CALLSIGN_PI_LAST ) ) { |
604 callSign += "W"; |
580 callSign += "W"; |
605 callSign += iterateCallSign( WXXX_CALLSIGN_PI_FIRST, programmeIdentification ); |
581 callSign += iterateCallSign( WXXX_CALLSIGN_PI_FIRST, programmeIdentification ); |
606 } |
582 } |
607 // 3 letter only call signs |
583 // 3 letter only call signs |
608 else if(( programmeIdentification >= XXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= XXX_CALLSIGN_PI_LAST)) { |
584 else if ( ( programmeIdentification >= XXX_CALLSIGN_PI_FIRST ) && ( programmeIdentification <= XXX_CALLSIGN_PI_LAST ) ) { |
609 callSign += callSignString( programmeIdentification ); |
585 callSign += callSignString( programmeIdentification ); |
610 } |
586 } else { |
611 else |
|
612 { |
|
613 LOG( "RadioStation::piCodeToCallSign - Unhandled else" ); |
587 LOG( "RadioStation::piCodeToCallSign - Unhandled else" ); |
614 } |
588 } |
615 |
589 |
616 LOG_FORMAT( "RadioStation::piCodeToCallSign, call sign: %s", GETSTRING(callSign) ); |
590 LOG_FORMAT( "RadioStation::piCodeToCallSign, call sign: %s", GETSTRING(callSign) ); |
617 |
591 |
624 QString RadioStation::iterateCallSign( int piBase, int programmeIdentification ) |
598 QString RadioStation::iterateCallSign( int piBase, int programmeIdentification ) |
625 { |
599 { |
626 QString callSign; |
600 QString callSign; |
627 LOG_FORMAT( "RadioStation::iterateCallSign base: %d", piBase ); |
601 LOG_FORMAT( "RadioStation::iterateCallSign base: %d", piBase ); |
628 |
602 |
629 int sum(0), i(0); |
603 int sum = 0; |
630 |
604 int i = 0; |
631 while( sum < programmeIdentification ) { |
605 while( sum < programmeIdentification ) { |
632 i++; |
606 ++i; |
633 sum = piBase + i * 676 + 0 + 0; |
607 sum = piBase + i * 676 + 0 + 0; |
634 } |
608 } |
635 callSign += callSignChar( i - 1 ); |
609 callSign += callSignChar( i - 1 ); |
636 |
610 |
637 int tmpSum( sum - 676 ); |
611 int tmpSum( sum - 676 ); |
638 sum -= 676; |
612 sum -= 676; |
639 i = 0; |
613 i = 0; |
640 while( sum <= programmeIdentification ) { |
614 while( sum <= programmeIdentification ) { |
641 i++; |
615 ++i; |
642 sum = tmpSum + 0 + i * 26 + 0; |
616 sum = tmpSum + 0 + i * 26 + 0; |
643 } |
617 } |
644 callSign += callSignChar( i - 1 ); |
618 callSign += callSignChar( i - 1 ); |
645 |
619 |
646 tmpSum = sum - 26; |
620 tmpSum = sum - 26; |
647 sum -= 26; |
621 sum -= 26; |
648 i = 0; |
622 i = 0; |
649 while( sum <= programmeIdentification ) { |
623 while( sum <= programmeIdentification ) { |
650 i++; |
624 ++i; |
651 sum = tmpSum + 0 + 0 + i; |
625 sum = tmpSum + 0 + 0 + i; |
652 } |
626 } |
653 callSign += callSignChar( i - 1 ); |
627 callSign += callSignChar( i - 1 ); |
654 |
628 |
655 return callSign; |
629 return callSign; |
682 } |
656 } |
683 return '?'; |
657 return '?'; |
684 } |
658 } |
685 |
659 |
686 /** |
660 /** |
687 * Detach from the implicitly shared data |
|
688 */ |
|
689 void RadioStation::detach() |
|
690 { |
|
691 if ( !isDetached() ) { |
|
692 RadioStationPrivate* newData = new RadioStationPrivate( *mData ); |
|
693 |
|
694 decrementReferenceCount(); |
|
695 |
|
696 newData->ref = 1; |
|
697 mData = newData; |
|
698 |
|
699 // The shared null instance of the data has its preset index set to -200 (RadioStation::SharedNull). |
|
700 // We change the preset index of the detached data to -100 (RadioStation::Invalid) just to ease |
|
701 // debugging. This guarantees that the only instance that has value -200 is the actual shared null. |
|
702 #ifdef _DEBUG |
|
703 if ( mData->mPresetIndex == RadioStation::SharedNull ) { |
|
704 mData->mPresetIndex = RadioStation::Invalid; |
|
705 } |
|
706 #endif |
|
707 } |
|
708 } |
|
709 |
|
710 /** |
|
711 * Checks if the class is detached from implicitly shared data |
661 * Checks if the class is detached from implicitly shared data |
712 */ |
662 */ |
713 bool RadioStation::isDetached() const |
663 bool RadioStation::isDetached() const |
714 { |
664 { |
715 return mData->ref == 1; |
665 return mData->ref == 1; |